cardif_windows.c

来自「linux 下通过802.1认证的安装包」· C语言 代码 · 共 2,063 行 · 第 1/5 页

C
2,063
字号
  case WAIT_IO_COMPLETION:
	  debug_printf(DEBUG_NORMAL, "WAIT_IO_COMPLETION\n");
	  break;

  case WAIT_OBJECT_0:
	  // The send was probably successful.  Double check GetLastError() to be sure.
	  success = GetLastError();

	  // ERROR_IO_PENDING means that there is another handler waiting to be triggered
	  // on the same device.  Since we will always have a read handle pending, we should
	  // always get an ERROR_IO_PENDING following a send.
	  if ((success != ERROR_SUCCESS) && (success != ERROR_IO_PENDING))
	  {
		  ipc_events_error(ctx, IPC_EVENT_ERROR_SEND_FAILED, ctx->desc);
		  lpMsgBuf = GetLastErrorStr(success);
  		  debug_printf(DEBUG_NORMAL, "Send was not entirely successful in interface '%s'.  Error was : %s\n",
			  ctx->desc, lpMsgBuf);
		  LocalFree(lpMsgBuf);
		  result = XEGENERROR;
	  }
	
	  break;

  case WAIT_TIMEOUT:
	  success = GetLastError();

	  if ((success != ERROR_SUCCESS) && (success != ERROR_IO_PENDING))
	  {
		  lpMsgBuf = GetLastErrorStr(success);
		  debug_printf(DEBUG_NORMAL, "Attempt to send the frame timed out on interface '%s'!  Error was : %s\n", ctx->desc, lpMsgBuf);
		  LocalFree(lpMsgBuf);
		  ipc_events_error(ctx, IPC_EVENT_ERROR_SEND_FAILED, ctx->desc);
		  retval = XEGENERROR;
	  }
	  else
	  {
		  debug_printf(DEBUG_NORMAL, "Frame was delayed on interface '%s' while trying to be sent.  (This should be harmless.)\n", ctx->desc);
		  retval = XENONE;
	  }
	  break;

  case WAIT_FAILED:
	  ipc_events_error(ctx, IPC_EVENT_ERROR_SEND_FAILED, ctx->desc);
	  lpMsgBuf = GetLastErrorStr(GetLastError());
	  debug_printf(DEBUG_NORMAL, "Wait for frame to be sent failed on interface '%s'!   Error was : %s\n", ctx->desc,
		  lpMsgBuf);
	  LocalFree(lpMsgBuf);
	  retval = XEGENERROR;
	  break;

  default:
	  ipc_events_error(ctx, IPC_EVENT_ERROR_SEND_FAILED, ctx->desc);
	  lpMsgBuf = GetLastErrorStr(GetLastError());
	  debug_printf(DEBUG_NORMAL, "Unknown failure code returned on interface '%s'.   Error was : %s\n", 
		  ctx->desc, lpMsgBuf);
	  LocalFree(lpMsgBuf);
	  retval = XEGENERROR;
	  break;
  }

  CloseHandle(hEvent);

  memset(ctx->sendframe, 0x00, FRAMESIZE);
  ctx->send_size = 0;
  
  // Clear out the receive buffer so we don't accidently try to process it
  // again.
  if (ctx->recvframe != NULL)
    {
      memset(ctx->recvframe, 0x00, FRAMESIZE);
      ctx->recv_size = 0;
    }

  return retval;
}

/**
 * \brief Verify that the frame we got is something we care about.  If not, discard it.
 *
 * @param[in] ctx   The context that contains the interface that we want to receive
 *                  a frame on.
 *
 * \retval XENOFRAMES there are no frames available to process
 * \retval XEMALLOC there was a memory allocation error
 * \retval >0 the number of bytes returned
 *
 * \todo Fix up 888e check to allow preauth data to come through as well.
 **/
int cardif_getframe(context *ctx)
{
  char dot1x_default_dest[6] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x03};
  struct config_globals *globals = NULL;
  wireless_ctx *wctx = NULL;

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

  globals = config_get_globals();

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

  wctx = (wireless_ctx *)ctx->intTypeData;
  if (wctx != NULL)
  {
	if (TEST_FLAG(wctx->flags, WIRELESS_SCANNING))
	{
		// This message would probably freak out most users, so only display
		// it in debug mode.
		debug_printf(DEBUG_INT, "Got a frame while scanning..  Checking if we can auth.\n");

		// If we already have information in the SSID cache about this network, then we should
		// cancel the scan in progress, and do the authentication.  Also, because we won't ever
		// have information in the scan cache about hidden networks, if we believe the network is
		// hidden, we should also move on. Otherwise, we should allow the scan to continue.
		debug_printf(DEBUG_INT, "Known SSID : %s\n", wctx->cur_essid);
		if ((config_ssid_ssid_known(wctx, wctx->cur_essid) == TRUE) || (TEST_FLAG(ctx->flags, CONFIG_NET_IS_HIDDEN)))
		{
			debug_printf(DEBUG_INT, "We know enough to authenticate.  Canceling scan.\n");
			timer_cancel(ctx, SCANCHECK_TIMER);
			UNSET_FLAG(wctx->flags, WIRELESS_SCANNING);
			wireless_sm_change_state(ASSOCIATED, ctx);
		}
		else 
		{
			debug_printf(DEBUG_INT, "We don't know enough to complete an authentication.  Discarding.\n");
			ctx->recv_size = 0;
			return XENONE;
		}
	}
  }

  if ((ctx->recvframe == NULL)) return XENOFRAMES;

  // Make sure that the frame we got is for us..
  if ((memcmp(&ctx->source_mac[0], &ctx->recvframe[0], 6) == 0) ||
      ((memcmp(&ctx->recvframe[0], &dot1x_default_dest[0], 6) == 0) &&
       (memcmp(&ctx->recvframe[6], &ctx->source_mac[0], 6) != 0)))
    {
      // Since we now know this frame is for us, record the address it
      // came from.
      snmp_dot1xSuppLastEapolFrameSource((uint8_t *)&ctx->recvframe[6]);

	  switch (globals->destination)
		{
			case DEST_AUTO:
			// If it is a wired interface, only change the destination if
			// the recieved frame destination isn't the multicast address.
			if (ctx->intType != ETH_802_11_INT)
			{
				if (memcmp(&ctx->recvframe[0], dot1x_default_dest, 6) == 0)
				{
					break;
				}
				// Otherwise, fall through.
			}

			case DEST_SOURCE:
			if (memcmp(ctx->dest_mac, &ctx->recvframe[6], 6) != 0)
			{
				debug_printf(DEBUG_INT, "Changing destination mac to source on '%s'.\n", ctx->desc);
			}
			memcpy(ctx->dest_mac, &ctx->recvframe[6], 6);
			break;

			case DEST_MULTICAST:
			memcpy(ctx->dest_mac, dot1x_default_dest, 6);
			break;

			case DEST_BSSID:
			cardif_GetBSSID(ctx, ctx->dest_mac);
			break;

			default:
				debug_printf(DEBUG_NORMAL, "Unknown destination mode on interface '%s'!\n", ctx->desc);
			break;
	  }

	  // Make sure it is 888e.
	  if ((ctx->recvframe[12] != 0x88) || (ctx->recvframe[13] != 0x8e))
	  {
		  debug_printf(DEBUG_INT, "An invalid frame managed to sneak "
			  "through interface '%s'!  Killing it!\n", ctx->desc);
		  debug_hex_dump(DEBUG_INT, ctx->recvframe, 16);

		  FREE(ctx->recvframe);
		  ctx->recv_size = 0;

		  return XENOFRAMES;
	  }

	  debug_printf(DEBUG_INT, "Got Frame of size %d on interface '%s' : \n", ctx->recv_size, ctx->desc);
	  debug_hex_dump(DEBUG_INT, ctx->recvframe, ctx->recv_size);

	  snmp_dot1xSuppEapolFramesRx();

      return ctx->recv_size;
    }

  // Otherwise it isn't for us. 
  debug_printf(DEBUG_INT, "Got a frame, not for us.\n");
  debug_hex_dump(DEBUG_INT, ctx->recvframe, 16);

  return XENOFRAMES;
}

/**
 * \brief Set up an event handler to let us know when we got a frame from the network.
 *
 * @param[in] ctx   The context that contains the interface that we want to 
 *                  receive data on.
 *
 * \retval XEMALLOC on memory allocation error
 * \retval XEGENERROR on general error
 * \retval XENONE on success
 **/
int cardif_setup_recv(context *ctx)
{
  int newsize=0;  
  struct win_sock_data *sockData = NULL;
  uint8_t *resultframe = NULL;
  int resultsize = 0;
  struct config_globals *globals = NULL;
  LPVOID lpMsgBuf = NULL;
  ULONG breadd = 0;
  LPOVERLAPPED lovr;
  DWORD result = 0;

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

  globals = config_get_globals();

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

  sockData = ctx->sockData;

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

  resultsize = FRAMESIZE; 

  lovr = event_core_get_ovr(sockData->devHandle);
  if (lovr == NULL)
  {
	  debug_printf(DEBUG_NORMAL, "The device handle doesn't appear to have an event handler "
		  "registered on interface '%s'!\n", ctx->desc);
	  ipc_events_error(ctx, IPC_EVENT_ERROR_EVENT_HANDLE_FAILED, ctx->desc);
	  return XEMALLOC;
  }

  if (HasOverlappedIoCompleted(lovr) == FALSE)
  {
	  // The last I/O request we had set up never finished.  So, we don't want to schedule a 
	  // a new one.  (Or weird things happen.)
	  debug_printf(DEBUG_NORMAL, "Windows reported that an overlapped I/O had not completed on interface '%s' even though the object was signaled.  Please attempt your authentication again.  If the problem persists, please report it to the Open1X mailing list.\n",
		  ctx->desc);
	  return XENONE;
  }

  // Clear the existing frame storage buffer.  (If needed.)
//  FREE(sockData->frame);
  sockData->size = 0;


  if (sockData->frame == NULL)
    {
	  sockData->frame = Malloc(FRAMESIZE);
	  if (sockData->frame == NULL)
	  {
      debug_printf(DEBUG_INT, "Couldn't allocate memory for incoming frame!\n");
	  ipc_events_malloc_failed(ctx);
      return XEMALLOC;
	  }
    }

  if (sockData->hEvent == INVALID_HANDLE_VALUE)
  {
	// Establish an event that will trigger to let us know that we have data.
	sockData->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (sockData->hEvent == INVALID_HANDLE_VALUE)
	{
		debug_printf(DEBUG_NORMAL, "Couldn't create a valid event handle on interface '%s'!\n", ctx->desc);
		ipc_events_error(ctx, IPC_EVENT_ERROR_EVENT_HANDLE_FAILED, ctx->desc);
		FREE(sockData->frame);
		return XEGENERROR;
	}

	memset(lovr, 0x00, sizeof(OVERLAPPED));

    lovr->hEvent = sockData->hEvent;
    event_core_bind_hevent(sockData->devHandle, sockData->hEvent);
  }
  else
  {
	  if (ResetEvent(sockData->hEvent) == 0)
	  {
		  debug_printf(DEBUG_NORMAL, "Couldn't reset event handler for interface '%s'.\n", ctx->desc);
		  FREE(sockData->frame);
		  return XEGENERROR;
	  }
	  lovr->hEvent = sockData->hEvent;
  }

  if (resultsize != FRAMESIZE) 
  {
	  debug_printf(DEBUG_NORMAL, "The desired frame size has change from when we originally set it.  This could indicate a memory corruption error.  Please report it to the Open1X mailing list!\n");
  }

  if (ReadFile(sockData->devHandle, sockData->frame, resultsize, &sockData->size, lovr) != 0)
  {
	  lpMsgBuf = GetLastErrorStr(GetLastError());
	  debug_printf(DEBUG_NORMAL, "Error setting up frame listener on interface '%s'.  Error was : %s\n", 
		  ctx->desc, lpMsgBuf);
	  LocalFree(lpMsgBuf);
	  FREE(sockData->frame);
	  return XEGENERROR;
  }

  return XENONE;
}

/**
 * \brief Set the state needed to associate to a WPA enabled AP, and actually
 *        do a WPA authentication.
 *
 * @param[in] ctx   The context that contains the interface that we want to enable 
 *                  WPA set for.
 *
 * \retval XEMALLOC on memory allocation error
 * \retval XENONE on success
 **/
int cardif_enable_wpa_state(context *ctx)
{
  if (!xsup_assert((ctx != NULL), "ctx != NULL", FALSE))
    return XEMALLOC;

  if (wireless == NULL) return XEMALLOC;

  if (wireless->wpa_state == NULL) return XEMALLOC;

  debug_printf(DEBUG_INT, "WPA: Enabling WPA state on interface %s.\n", ctx->intName);

  return wireless->wpa_state(ctx, TRUE);
}

/**
 * \brief Clear the state needed to associate to a WPA enabled AP, and actually
 *        do a WPA authentication.
 *
 * @param[in] ctx   The context that contains the interface that we want to clear
 *                  WPA state on.
 *
 * \retval XEMALLOC a memory allocation error occurred
 * \retval XENONE on success
 **/
int cardif_disable_wpa_state(context *ctx)
{
  if (!xsup_assert((ctx != NULL), "ctx != NULL", FALSE))
    return XEMALLOC;

  if (wireless == NULL) return XEMALLOC;

  if (wireless->wpa_state == NULL) return XEMALLOC;

  return wireless->wpa_state(ctx, FALSE);
}

/**
 * \brief Enable WPA support on an interface.
 *
 * Windows already should have WPA enabled, so this function is only needed as a stub.
 *
 * @param[in] ctx   The context that contains the interface to enable WPA on.
 *
 * \retval XENONE always returned for Windows
 **/
int cardif_enable_wpa(context *ctx)
{
	return XENONE;
}

/**
 * \brief Call this when we roam to a different AP, or disassociate from an AP.
 *
 * @param[in] ctx   The context for the interface that we want to use WEP to 
 *                  associate with.
 *
 * \retval XEMALLOC on memory allocation errors
 * \retval XENONE on success
 **/
int cardif_wep_associate(context *ctx, int zeros)
{
  if (!xsup_assert((ctx != NULL), "ctx != NULL", FALSE))
    return XEMALLOC;

  if (wireless == NULL) return XEMALLOC;

  if (!config_ssid_using_wep(ctx->intTypeData))
    {
      debug_printf(DEBUG_INT, "Doing WPA/WPA2 mode! Not "
		   "setting/unsetting keys.\n");
      return XENONE;
    }

  return wireless->wep_associate(ctx, zeros); 
}

/**
 * \brief Validate an interface.  (Basically, see if it is an interface we know how

⌨️ 快捷键说明

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