⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cardif_linux_rtnetlink.c

📁 linux 下通过802.1认证的安装包
💻 C
📖 第 1 页 / 共 3 页
字号:
/**
 * File: cardif_linux_rtnetlink.c
 *
 * Licensed under a dual GPL/BSD license.  (See LICENSE file for more info.)
 *
 * Authors: Chris.Hessing@utah.edu
 *
 * $Id: cardif_linux_rtnetlink.c,v 1.103.2.21 2007/05/20 22:36:34 chessing Exp $
 * $Date: 2007/05/20 22:36:34 $
 *
 **/

#ifdef LINUX_FRAMER

// Use kernel headers
#define HEADERS_KERNEL

#include <unistd.h>
#include <sys/socket.h>
#include <linux/compiler.h>
#include <iwlib.h>
#include <sys/ioctl.h>
#include "netlink.h"
#include "rtnetlink.h"
#include <linux/if.h>
#include <linux/if_packet.h>
#include <math.h>

#include "wireless_copy.h"
#include "xsupconfig.h"
#include "context.h"
#include "xsup_common.h"
#include "xsup_debug.h"
#include "xsup_err.h"
#include "wireless_sm.h"
#include "cardif_linux.h"
#include "statemachine.h"
#include "../cardif.h"
#include "wpa.h"
#include "wpa2.h"
#include "eap_sm.h"
#include "eap_types/mschapv2/mschapv2.h"
#include "config_ssid.h"
#include "eapol_key_type254.h"
#include "timer.h"
#include "mic.h"
#include "event_core.h"
#include "cardif_linux_wext.h"
#include "cardif_linux_rtnetlink.h"

#ifdef USE_EFENCE
#include <efence.h>
#endif

// Define this, so the compiler doesn't complain.
extern char *if_indextoname(unsigned int, char *);

#define INT_DEL    0
#define INT_NEW    1

static int rtnl_sock=-1;
static struct sockaddr_nl rtnl_data;

#ifndef IWEVCUSTOM
#warning IWEVCUSTOM is not defined!  We will define it, and try to continue!
#define IWEVCUSTOM   0x8C02
#endif

#ifndef IW_CUSTOM_MAX
#warning IW_CUSTOM_MAX is not defined!  You should upgrade to a more current version of wireless extensions.  We will attempt to define it ourselves, but the results may not be good.
#define IW_CUSTOM_MAX  256  // In bytes, matches current WE versions. (11/14/05)
#endif

// Forward defs to avoid compiler warnings.
void cardif_linux_rtnetlink_process_token(context *ctx,
					  struct iw_event *iwe);

extern unsigned int if_nametoindex(const char *);

/********************************************************
 *
 * Do whatever is needed to establish a netlink socket so that we can
 * catch events, and take action.
 *
 ********************************************************/
void cardif_linux_rtnetlink_init(context *ctx)
{
  rtnl_sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
  
  if (rtnl_sock < 0)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't establish an rtnetlink socket!  Some functionality won't be available!\n");
      return;
    }

  memset((char *)&rtnl_data, 0x00, sizeof(rtnl_data));

  rtnl_data.nl_family = AF_NETLINK;
  rtnl_data.nl_groups = RTMGRP_LINK;

  if (bind(rtnl_sock, (struct sockaddr *)&rtnl_data, sizeof(rtnl_data)) < 0)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't bind netlink socket!  Some functionality won't be available!\n");
      close(rtnl_sock);
      return;
    }

  event_core_register(rtnl_sock, ctx, cardif_linux_rtnetlink_check_event, 
		      HIGH_PRIORITY, "rtnetlink handler");

  cardif_linux_rtnetlink_set_linkmode(ctx, IF_LINK_MODE_DORMANT);
}

/********************************************************
 *
 * Do whatever is needed to shutdown the netlink socket that we set up.
 *
 ********************************************************/
void cardif_linux_rtnetlink_cleanup(context *ctx)
{
  debug_printf(DEBUG_INT, "Called cardif_linux_rtnetlink_cleanup()!\n");

  cardif_linux_rtnetlink_set_operstate(ctx, XIF_OPER_UP);
  cardif_linux_rtnetlink_set_linkmode(ctx, XIF_LINK_MODE_DEFAULT);

  // Close the rtnetlink socket.
  close(rtnl_sock);
}

/*********************************************************************
 *
 * Get the wireless extensions version that this driver was built with.
 *
 *********************************************************************/
int cardif_linux_rtnetlink_get_we_ver(context *intdata)
{
  struct iwreq iwr;
  struct iw_range *range = NULL;
  char buffer[sizeof(iwrange)*2];
  int sock;

  if (!xsup_assert((intdata != NULL), "intdata != NULL", FALSE))
    return XEMALLOC;

  memset(buffer, 0x00, (sizeof(iwrange)*2));

  iwr.u.data.pointer = (caddr_t) buffer;
  iwr.u.data.length = sizeof(buffer);
  iwr.u.data.flags = 0;

  sock = cardif_get_socket(intdata);
  if (iw_get_ext(sock, intdata->intName, SIOCGIWRANGE, &iwr) < 0)
    {
      debug_printf(DEBUG_NORMAL, "Error with ioctl SIOCGIWRANGE (Error: %s)\n",
		   strerror(errno));
      return -1;
    }

  range = (struct iw_range *)buffer;

  return range->we_version_compiled;
}

/********************************************************
 *
 * Gather the data that was returned from a scan.
 *
 ********************************************************/
void cardif_linux_rtnetlink_reap(context *intdata, char *data, int len)
{
  struct stream_descr stream;
  struct iw_event iwe;
  int retval;

  if (!xsup_assert((intdata != NULL), "intdata != NULL", FALSE))
    return;

  if (!xsup_assert((data != NULL), "data != NULL", FALSE))
    return;

  xsup_assert((len >= 0), "len >= 0", TRUE);
  xsup_assert((len < 65001), "len < 65001", TRUE);

  iw_init_event_stream(&stream, data, len);
  do
    {
#ifdef NEW_IWLIB
      retval = iw_extract_event_stream(&stream, &iwe, 
				       cardif_linux_rtnetlink_get_we_ver(intdata));
#else
      retval = iw_extract_event_stream(&stream, &iwe);
#endif

      if (retval == 1)  // Then we got something
	{
	  cardif_linux_rtnetlink_process_token(intdata, &iwe);
	} else {
	  switch (retval)
	    {
	    case 0:
	      // No error.
	      break;

	    case -1:debug_printf(DEBUG_NORMAL, "Invalid event!\n");
	      break;

	    case 2:debug_printf(DEBUG_NORMAL, "Unknown event found. Skipping."
				"(Event %04X) (Not supported in wireless "
				"extensions %d?)\n", iwe.cmd, WIRELESS_EXT);
	      break;

	    case -2:debug_printf(DEBUG_NORMAL, "Invalid event data. Skipping."
				 "\n");
	      break;

	    default:debug_printf(DEBUG_NORMAL, "Unknown result code from "
				 "iw_extract_event_stream(). (Result was %d)"
				 "\n", retval);
	      break;
	    }
	}
    }
  while (retval > 0);
}

/*******************************************************
 *
 * Check to see if we have data in the returned scan buffer, even if 
 * we didn't get a scan complete event.  (Some cards may not send the
 * scan complete event.)
 *
 *******************************************************/
uint8_t cardif_linux_rtnetlink_check_nets(context *idata)
{
  struct lin_sock_data *sockData = NULL;
  struct iwreq iwr;
  char *buffer = NULL;
  uint16_t buf_size = 8192;
  wireless_ctx *wctx = NULL;

  if (!xsup_assert((idata != NULL), "idata != NULL", FALSE))
    return XEMALLOC;

  if (!xsup_assert((idata->intTypeData != NULL), "idata->intTypeData != NULL",
		   FALSE))
    return XEMALLOC;

  wctx = (wireless_ctx *)idata->intTypeData;

  if (!TEST_FLAG(wctx->flags, WIRELESS_SCANNING)) 
    {
      return XENONE;
    }

  debug_printf(DEBUG_INT, "Checking for returned SSID information....\n");

  sockData = idata->sockData;

  if (!xsup_assert((buf_size != 0), "buf_size != 0", TRUE))
      return XEMALLOC;
  
  if (!xsup_assert((sockData != NULL), "sockData != NULL", FALSE))
    return XEMALLOC;

  buffer = (char *)Malloc(buf_size);
  if (buffer == NULL)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't allocate memory for scan buffer!"
		   "\n");
      return XEMALLOC;
    }

  iwr.u.data.pointer = buffer;
  iwr.u.data.flags = 0;
  iwr.u.data.length = buf_size;

  strcpy(iwr.ifr_name, idata->intName);
  
  if (ioctl(sockData->sockInt, SIOCGIWSCAN, &iwr) < 0)
    {
      if (errno == E2BIG)
	{
	  // Our return results are too big for our default buffer.  So,
	  // allocate more and try again!
	  
	  FREE(buffer);
	  buf_size *= 2;

	  buffer = (char *)Malloc(buf_size);
	  if (!buffer)
	    {
	      debug_printf(DEBUG_NORMAL, "Couldn't allocate memory for scan "
			   "buffer!\n");
	      return XEMALLOC;
	    }

	  iwr.u.data.pointer = buffer;
	  iwr.u.data.length = buf_size;

	  while (ioctl(sockData->sockInt, SIOCGIWSCAN, &iwr) < 0)
	    {
	      FREE(buffer);
	      
	      if (buf_size > 60000)
		{
		  debug_printf(DEBUG_NORMAL, "Buffer size to allocate has "
			       "become unreasonable!  (If you really have "
			       "that many SSIDs, you won't get much data "
			       "across the network anyway!)\n");
		  return -1;
		}

	      buf_size *= 2;

	      buffer = (char *)Malloc(buf_size);
	      if (!buffer)
		{
		  debug_printf(DEBUG_NORMAL, "Couldn't allocate memory for scan buffer!\n");
		  return XEMALLOC;
		}

	      iwr.u.data.pointer = buffer;
	      iwr.u.data.length = buf_size;
	    }
	}
      else
	{
	  if (errno == EAGAIN)
	    {
	      debug_printf(DEBUG_INT, "No data available! (%s)\n", 
			   strerror(errno));
	      return XENONE;
	    }
	  else
	    {
	      debug_printf(DEBUG_NORMAL, "Error with scan results!\n");
	      debug_printf(DEBUG_NORMAL, "Error was : %s\n", strerror(errno));
	      UNSET_FLAG(wctx->flags, WIRELESS_SCANNING);
	      return -1;
	    }
	}
    }

  debug_printf(DEBUG_NORMAL, "Scan complete.\n");

  // Cancel the scancheck timer, so it doesn't continue to fire.
  timer_cancel(idata, SCANCHECK_TIMER);

  if (iwr.u.data.length <= 0) 
    {
      FREE(buffer);
      return XENONE;
    }

  // Then harvest the data.
  debug_printf(DEBUG_INT, "Reaping data. (Size : %d)\n", iwr.u.data.length);
  debug_hex_dump(DEBUG_INT, (uint8_t *)buffer, iwr.u.data.length);
  cardif_linux_rtnetlink_reap(idata, (char *)buffer, iwr.u.data.length);
      
  UNSET_FLAG(wctx->flags, WIRELESS_SCANNING);

  // Clean up after ourselves.
  FREE(buffer);

  return XDATA;
}

/***********************************************************
 *
 * Check the MAC that we were given.  If it is all 0s, 4s, or Fs then the
 * event is a disassociation.  If it isn't then it is an association.
 *
 ***********************************************************/
int cardif_linux_rtnetlink_validate(context *idata, uint8_t *mac)
{
  char newmac[6];

  if (!xsup_assert((idata != NULL), "idata != NULL", FALSE))
    return XEMALLOC;

  if (!xsup_assert((mac != NULL), "mac != NULL", FALSE))
    return XEMALLOC;

  // Is it a disassociation?
  memset(newmac, 0x00, 6);
  if (memcmp(newmac, mac, 6) == 0)
    {
      return FALSE;
    }

  memset(newmac, 0x44, 6);
  if (memcmp(newmac, mac, 6) == 0)
    {
      return FALSE;
    }

  memset(newmac, 0xff, 6);
  if (memcmp(newmac, mac, 6) == 0)
    {
      return FALSE;
    }
  
  // Otherwise, it was an association
  return TRUE;
}


/**********************************************************************
 *
 * Process a SIOCGIWAP event.
 *
 **********************************************************************/
void cardif_linux_rtnetlink_process_SIOCGIWAP(context *idata,
					      struct iw_event *iwe)
{
  char mac[6];
  int assoc;
  struct config_globals *globals = NULL;
  wireless_ctx *wctx = NULL;

  if (!xsup_assert((idata != NULL), "idata != NULL", FALSE))
    return;

  if (!xsup_assert((idata->intTypeData != NULL), "idata->intTypeData != NULL",
		   FALSE))
    return;

  if (!xsup_assert((iwe != NULL), "iwe != NULL", FALSE))
    return;

  wctx = (wireless_ctx *)idata->intTypeData;

  memcpy(mac, iwe->u.ap_addr.sa_data, 6);
  debug_printf(DEBUG_INT, "AP MAC : ");
  debug_hex_printf(DEBUG_INT, (uint8_t *)mac, 6);

#warning Check this!
  if (TEST_FLAG(wctx->flags, WIRELESS_SCANNING))
    {
      config_ssid_add_bssid(wctx, mac);
    } else {
      globals = config_get_globals();

      if (!xsup_assert((globals != NULL), "globals != NULL", FALSE))
	return;

      assoc = cardif_linux_rtnetlink_validate(idata, (uint8_t *)&mac);
      if (assoc)
	{
	  // We have changed to associated mode.  Populate the destination
	  // MAC with the BSSID, as long as we are in auto mode.
	  
	  SET_FLAG(wctx->flags, WIRELESS_SM_ASSOCIATED);
	  UNSET_FLAG(wctx->flags, WIRELESS_SM_STALE_ASSOCIATION);
	  
	  if (globals->destination == DEST_AUTO)
	    memcpy(idata->dest_mac, mac, 6);
	  
	} else {
	  UNSET_FLAG(wctx->flags, WIRELESS_SM_ASSOCIATED);
	  UNSET_FLAG(wctx->flags, WIRELESS_SM_STALE_ASSOCIATION);
	}
    }
}

/**********************************************************************
 *
 * Process a SIOCGIWESSID event.
 *
 **********************************************************************/
void cardif_linux_rtnetlink_process_SIOCGIWESSID(context *ctx,
						 struct iw_event *iwe)
{
  char essid[IW_ESSID_MAX_SIZE+1];
  wireless_ctx *wctx = NULL;

  if (!xsup_assert((ctx != NULL), "ctx != NULL", FALSE))
    return;

  if (!xsup_assert((ctx->intTypeData != NULL), "ctx->intTypeData != NULL",
		   FALSE))
    return;

  if (!xsup_assert((iwe != NULL), "iwe != NULL", FALSE))
    return;

  wctx = (wireless_ctx *)ctx->intTypeData;

  memset(essid, 0x00, IW_ESSID_MAX_SIZE+1);
  
  memcpy(essid, iwe->u.essid.pointer, iwe->u.essid.length);
  essid[iwe->u.essid.length] = '\0';

#warning Check this!
  if (TEST_FLAG(wctx->flags, WIRELESS_SCANNING))
    {
      debug_printf(DEBUG_INT, "ESSID : %s\n", essid);
      
      config_ssid_add_ssid_name(wctx, essid);
    } else {
      debug_printf(DEBUG_NORMAL, "Got a get SSID event!? "
		   "Notify your wireless driver maintainer.\n");
    }
}

/*****************************************************************
 *
 * Process an SIOCSIWESSID.
 *
 *****************************************************************/
void cardif_linux_rtnetlink_process_SIOCSIWESSID(context *ctx,
						 struct iw_event *iwe)
{
  char essid[IW_ESSID_MAX_SIZE+1];
  wireless_ctx *wctx = NULL;
  char wpaie[24];

  if (!xsup_assert((ctx != NULL), "ctx != NULL", FALSE))
    return;

  if (!xsup_assert((ctx->intTypeData != NULL), "ctx->intTypeData != NULL",
		   FALSE))
    return;

  if (!xsup_assert((iwe != NULL), "iwe != NULL", FALSE))
    return;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -