• Main Page
  • Data Structures
  • Files
  • File List
  • Globals

wps.c

Go to the documentation of this file.
00001 
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <stdint.h>
00026 #include <string.h>
00027 #include <sys/ioctl.h>
00028 #include <glib.h>
00029 #include <glib-object.h>
00030 #include <unistd.h>
00031 #include "common.h"
00032 #include "wpa.h"
00033 #include "wps.h"
00034 #include "log.h"
00035 
00036 #define WPS_VERSION              0x10
00037 #define MAX_DEVICE_NAME          32
00038 
00039 #define WPS_STATE_UNCONFIGURED   0x01
00040 #define WPS_STATE_CONFIGURED     0x02
00041 
00042 #define WPS_PIN_CODE             0
00043 #define WPS_PUSH_BUTTON          4
00044 
00045 /* TLV defitions */
00046 #define WPS_VERSION_TLV                        0x104A
00047 #define WPS_STATE_TLV                          0x1044
00048 #define WPS_APSETUPLOCKED_TLV                  0x1057
00049 #define WPS_SELECTEDREGISTRAR_TLV              0x1041
00050 #define WPS_DEVICEPASSWORD_ID_TLV              0x1012
00051 #define WPS_SELECTEDREGISTRARCONFIGMETHODS_TLV 0x1053
00052 #define WPS_DEVICENAME_TLV                     0x1011
00053 #define WPS_UUID_E_TLV                         0x1047
00054 
00064 static int get_tlv_value(guchar* msg, guint msg_size, guint type,
00065                          guchar* value, guint value_len)
00066 {
00067         guint len = 0;
00068 
00069         if (msg_size < 4) {
00070                 DLOG_ERR("Message too short");
00071                 return -1;
00072         }
00073 
00074         // Find the TLV value
00075         while (len + 4 < msg_size)
00076         {
00077                 guint hi = msg[len];
00078                 guint lo = msg[len+1];
00079                 guint tmp_type = (hi << 8) + lo;
00080 
00081                 //DLOG_DEBUG("tmp_type: %04x", tmp_type);
00082 
00083                 guint length = 0;
00084 
00085                 hi = msg[len+2];
00086                 lo = msg[len+3];
00087 
00088                 length = (hi << 8) + lo;
00089 
00090                 // check the type
00091                 if (tmp_type == type)
00092                 {
00093                         if (length > value_len) {
00094                                 DLOG_ERR("Too much data for buffer (%d)",
00095                                          value_len);
00096                                 return -1;
00097                         }
00098                         if (len + 4 + length > msg_size) {
00099                                 DLOG_ERR("Message data too short?");
00100                                 return -1;
00101                         }
00102                         
00103                         memcpy(value, msg+len+4, length);
00104                         //DLOG_DEBUG("value: %04x", *value);
00105 
00106                         return length;
00107                 }
00108 
00109                 len = len + length + 4;
00110         }
00111 
00112         return -1;
00113 }
00120 void handle_wps_ie(unsigned char* p,
00121                    struct scan_results_t *scan_results,
00122                    unsigned int length)
00123 {
00124         guint value = 0;
00125         char device_name[MAX_DEVICE_NAME+1];
00126         guchar *uuid_e;
00127         gint len;
00128 
00129         if (length < 2) {
00130                 DLOG_ERR("WPS IE too short");
00131                 return;
00132         }
00133 #if 0
00134         unsigned int i;
00135         for (i=0;i<length;i++) {
00136                 DLOG_DEBUG("%02x", p[i]);
00137         }
00138 #endif
00139 
00140         /* Mandatory fields */
00141         if (get_tlv_value(p, length, WPS_VERSION_TLV, (unsigned char*)&value,
00142                           sizeof(value)) < 0 || value != WPS_VERSION) {
00143                 DLOG_ERR("Unknown WPS version received (%02x)", value);
00144                 return;
00145         }
00146 
00147         if (get_tlv_value(p, length, WPS_STATE_TLV, (unsigned char*)&value,
00148                           sizeof(value)) < 0) {
00149                 DLOG_ERR("Could not get WPS state");
00150                 return;
00151         }
00152 
00153         DLOG_DEBUG("WPS state: %s", value == WPS_STATE_CONFIGURED?"configured":
00154                    "unconfigured");
00155         
00156         scan_results->cap_bits |= WLANCOND_WPS;
00157 
00158         /* Everything else is optional */
00159         if (get_tlv_value(p, length, WPS_APSETUPLOCKED_TLV,
00160                           (unsigned char*)&value, sizeof(value)) < 0) {
00161                 //DLOG_ERR("Could not get ap_setup_locked");
00162         } else {
00163                 DLOG_DEBUG("ap_setup_locked: %d", value);
00164         }
00165 
00166         if (get_tlv_value(p, length, WPS_SELECTEDREGISTRAR_TLV,
00167                           (unsigned char*)&value, sizeof(value)) < 0) {
00168                 //DLOG_ERR("Could not get selected_registrar");
00169         } else if (value) {
00170                 DLOG_DEBUG("Device is selected registrar");
00171                 scan_results->cap_bits |= WLANCOND_WPS_CONFIGURED;
00172         }
00173 
00174         if (get_tlv_value(p, length, WPS_DEVICEPASSWORD_ID_TLV,
00175                           (unsigned char*)&value, sizeof(value)) < 0) {
00176                 //DLOG_ERR("Assuming PUSH and PIN");
00177                 // If AP does not give this info, let's assume the following
00178                 scan_results->cap_bits |= WLANCOND_WPS_PIN;
00179                 scan_results->cap_bits |= WLANCOND_WPS_PUSH_BUTTON;
00180         } else {
00181                 if (GUINT16_FROM_BE(value) == WPS_PIN_CODE) {
00182                         DLOG_DEBUG("PIN supported");
00183                         scan_results->cap_bits |= WLANCOND_WPS_PIN;
00184                 }
00185                 if (GUINT16_FROM_BE(value) == WPS_PUSH_BUTTON) {
00186                         DLOG_DEBUG("PBC supported");
00187                         scan_results->cap_bits |= WLANCOND_WPS_PUSH_BUTTON;
00188                 }
00189         }
00190 
00191         if ((len = get_tlv_value(p, length, WPS_DEVICENAME_TLV,
00192                                  (unsigned char*)&device_name,
00193                                  sizeof(device_name)-1)) < 0) {
00194                 //DLOG_ERR("Could not get device name");
00195         } else {
00196                 device_name[len] = '\0';
00197                 DLOG_DEBUG("Device name: %s", device_name);
00198         }
00199 
00200         uuid_e = g_malloc(MAX_UUID_E_LEN);
00201 
00202         if ((len = get_tlv_value(p, length, WPS_UUID_E_TLV,
00203                                  uuid_e, MAX_UUID_E_LEN)) < 0) {
00204                 DLOG_DEBUG("Could not get UUID-E");
00205                 g_free(uuid_e);
00206         } else {
00207                 scan_results->uuid_e = uuid_e;
00208         }
00209 
00210 #ifdef DEBUG_WPS
00211 
00212         if (get_tlv_value(p, length, WPS_SELECTEDREGISTRARCONFIGMETHODS_TLV,
00213                           (unsigned char*)&value, sizeof(value)) < 0) {
00214                 DLOG_ERR("Could not get config_methods");
00215         } else {
00216                 DLOG_DEBUG("Config_methods: %04x", GUINT16_FROM_BE(value));
00217         }
00218 
00219 #endif
00220 
00221         return;
00222 }

Generated on Wed Aug 10 2011 16:02:33 for WLAN Connection Daemon by  doxygen 1.7.1