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

📄 cardif_linux_rtnetlink.c

📁 linux 下通过802.1认证的安装包
💻 C
📖 第 1 页 / 共 3 页
字号:
      // There may be more than one message in the packet.  So, loop through!
      while (remain >= sizeof(struct nlmsghdr))
	{
	  // Make sure we have enough data for a real message.
	  if ((nlhead->nlmsg_len > remain) || 
	      ((nlhead->nlmsg_len - sizeof(struct nlmsghdr)) < 0))
	    {
	      debug_printf(DEBUG_NORMAL, "Invalid netlink message!\n");
	      break;
	    }
	  
	  // See what kind of message it is.
	  switch (nlhead->nlmsg_type)
	    {
	    case RTM_NEWLINK:
	      debug_printf(DEBUG_INT, "Got an RTM_NEWLINK!\n");
	      cardif_linux_rtnetlink_do_link(idata, nlhead,
					     nlhead->nlmsg_len, INT_NEW);
	      break;
	      
	    case RTM_DELLINK:
	      debug_printf(DEBUG_INT, "Got an RTM_DELLINK!\n");
	      cardif_linux_rtnetlink_do_link(idata, nlhead, 
					     nlhead->nlmsg_len, INT_DEL);
	      break;
	    }

	  // Find the aligned length of the message, so we can skip
	  // to the next message.
	  length = NLMSG_ALIGN(nlhead->nlmsg_len);

	  remain -= length;
	  
	  nlhead = (struct nlmsghdr *) ((char *)nlhead + length);
	}

      // If we have anything left, then there may be a problem.  So, report
      // the we may have a problem.
      if (remain > 0)
	{
	  debug_printf(DEBUG_NORMAL, "Extra bytes at the end of the netlink message.\n");
	}
    }

  // There may be situations where the wireless card driver can scan,
  // but doesn't provide an event when the scan has completed.  So,
  // we need to check if we have data, even if we don't have an event.
  return cardif_linux_rtnetlink_check_nets(idata);
}

/************************************************************
 *
 *  We got an RTM_NEWLINK or RTM_DELLINK message, so process it, and 
 *  decide how to proceed.
 *
 ************************************************************/
void cardif_linux_rtnetlink_do_link(context *intdata,
				    struct nlmsghdr *msg, int len, int type)
{
  struct ifinfomsg *ifinfo = NULL;
  int nlmsg_len, rtalen, rtlen;
  struct rtattr *rtattr = NULL;

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

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

  if (len < sizeof(struct ifinfomsg))
    {
      debug_printf(DEBUG_NORMAL, "Netlink message too short!\n");
      return;
    }

  // Get the actual message from the block.
  ifinfo = NLMSG_DATA(msg);

  // Find out how big the message is.
  nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));

  if ((msg->nlmsg_len - nlmsg_len) < 0)
    {
      debug_printf(DEBUG_NORMAL, "Message inside newlink isn't valid!\n");
      return;
    }

  rtattr = (struct rtattr *)(((char *)ifinfo) + nlmsg_len);

  rtalen = RTA_ALIGN(sizeof(struct rtattr));
  
  // Validate the attribute we have, and determine if it is for wireless,
  // or wired.
  while (RTA_OK(rtattr, (msg->nlmsg_len - nlmsg_len)))
    {
      switch (rtattr->rta_type)
	{
	case IFLA_UNSPEC:
	  debug_printf(DEBUG_INT, "IFLA_UNSPEC event.\n");
	  break;

	case IFLA_ADDRESS:
	  debug_printf(DEBUG_INT, "IFLA_ADDRESS event.\n");
	  break;

	case IFLA_BROADCAST:
	  debug_printf(DEBUG_INT, "IFLA_BROADCAST event.\n");
	  break;

	case IFLA_IFNAME:
	  // This is a non-wireless event. (Ignore it.)
	  debug_printf(DEBUG_INT, "IFLA_IFNAME event.\n");
	  break;

	case IFLA_MTU:
	  debug_printf(DEBUG_INT, "IFLA_MTU event.\n");
	  break;

	case IFLA_LINK:
	  debug_printf(DEBUG_INT, "IFLA_LINK event.\n");
	  break;

	case IFLA_WIRELESS:
	  // This is a wireless event.
	  cardif_linux_rtnetlink_ifla_wireless(intdata, ifinfo->ifi_index,
					       ((char *) rtattr)+rtalen,
					       rtattr->rta_len - rtalen);
	  break;

	case IFLA_OPERSTATE:
	  cardif_linux_rtnetlink_ifla_operstate(intdata, ifinfo->ifi_index,
						((char *) rtattr)+rtalen,
						rtattr->rta_len - rtalen);
	  break;

	default:
	  debug_printf(DEBUG_INT, "RTNetlink Event type %d\n", 
		       rtattr->rta_type);
	  break;
	}

      rtlen = msg->nlmsg_len - nlmsg_len;

      // Get the next attribute
      rtattr = RTA_NEXT(rtattr, rtlen);
    }
}

/***********************************************************
 *
 * Check the string that identifies the custom event that we got. And
 * act on it.
 *
 ***********************************************************/
void cardif_linux_rtnetlink_check_custom(context *intdata,
					 char *str)
{
  if (!xsup_assert((intdata != NULL), "intdata != NULL", FALSE))
    return;

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

  if (strncmp(str, "MLME-MICHAELMICFAILURE.indication", 33) == 0)
    {
      intdata->statemachine->MICfailures++;
      debug_printf(DEBUG_NORMAL, "MIC failure #%d!\n",
		   intdata->statemachine->MICfailures);
      
      if (strstr(str, " unicast ") != NULL)
	{
	  // The attempted attack was probably against the unicast key.
	  debug_printf(DEBUG_NORMAL, "MIC failure on unicast key!\n");
	  eapol_key_type254_request_new_key(intdata, 1);
	  intdata->send_size = 0;
	} else {
	  // The attempted attack was probably against the group key.
	  debug_printf(DEBUG_NORMAL, "MIC failure on group key!\n");
	  eapol_key_type254_request_new_key(intdata, 0);
	  intdata->send_size = 0;
	}

      if (intdata->statemachine->MICfailures >= 2)
	{
	  // The WPA/802.11i standard requires we assert countermeasures 
	  // for 60 seconds.
	  if (timer_check_existing(intdata, COUNTERMEASURE_TIMER))
	    {
	      debug_printf(DEBUG_NORMAL, "For some reason, we already have "
			   "a countermeasure timer in the queue!  Resetting "
			   "the timer!\n");
	      timer_reset_timer_count(intdata, COUNTERMEASURE_TIMER, 
				      MIC_COUNTERMEASURE_TIMEOUT);
	    } else {
	      debug_printf(DEBUG_NORMAL, "Enabling MIC countermeasures!\n");
	      timer_add_timer(intdata, COUNTERMEASURE_TIMER, 
			      MIC_COUNTERMEASURE_TIMEOUT,
			      NULL, &mic_disable_countermeasures);
	    }
	  cardif_countermeasures(intdata, TRUE);
	}
    }
}

/***********************************************************
 *
 * Check to see if we have become disassociated before the rekey_prob_timer
 * (found in profile.h) reaches 0.  If we have, it may indicate that we
 * have a card driver that resets the card on a key set.  This should only be
 * a problem with WEP and older card drivers.
 *
 ***********************************************************/
void cardif_linux_rtnetlink_check_key_prob(context *idata)
{
  struct config_globals *globals = NULL;

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

  globals = config_get_globals();

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

  if (timer_check_existing(idata, REKEY_PROB_TIMER))
    {
      if (!TEST_FLAG(globals->flags, CONFIG_GLOBALS_NO_FRIENDLY_WARNINGS))
	{
	  debug_printf(DEBUG_NORMAL, "** WARNING! ** You were disassocated "
		       "within a short time of setting a key!\nThis usually "
		       "means there is a problem with the card driver.\n"
		       "Please e-mail the developers for more information on "
		       "what this means. Be sure to include the type of card, "
		       "driver in use, and driver version number.\n");
	}
    }
}

/***********************************************************
 *
 * Process operstate events.
 *
 ***********************************************************/
void cardif_linux_rtnetlink_ifla_operstate(context *idata,
					   int ifindex, char *data, int len)
{
  if (!xsup_assert((idata != NULL), "idata != NULL", FALSE))
    return;

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

  debug_printf(DEBUG_INT, "Got a netlink OPERSTATE event!\n");

  debug_printf(DEBUG_INT, "OPERSTATE event on interface %d\n", ifindex);

  debug_printf(DEBUG_INT, "Event dump (%d) : \n", len);
  debug_hex_dump(DEBUG_INT, data, len);

  switch(data[0])
    {
    case XIF_OPER_UNKNOWN:
      debug_printf(DEBUG_INT, "Interface is in unknown state.\n");
      break;

    case XIF_OPER_NOTPRESENT:
      debug_printf(DEBUG_INT, "Interface is not present.\n");
      break;

    case XIF_OPER_DOWN:
      debug_printf(DEBUG_INT, "Interface is down.\n");
      break;

    case XIF_OPER_LOWERLAYERDOWN:
      debug_printf(DEBUG_INT, "Interface lower layer is down.\n");
      break;

    case XIF_OPER_DORMANT:
      debug_printf(DEBUG_INT, "Interface is dormant.\n");
      break;

    case XIF_OPER_UP:
      debug_printf(DEBUG_INT, "Interface is up.\n");
      break;

    default:
      debug_printf(DEBUG_INT, "Unknown interface state %d.\n", data[0]);
      break;
    }
}

/***********************************************************
 *
 * Process wireless events.
 *
 ***********************************************************/
void cardif_linux_rtnetlink_ifla_wireless(context *idata, 
					  int ifindex, char *data, int len)
{
  struct iw_event iwe;
  struct config_globals *globals = NULL;
  struct stream_descr stream;
  wireless_ctx *wctx = NULL;
  int intIndex = 0;
  int ret = 0;

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

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

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

  wctx = (wireless_ctx *)idata->intTypeData;

  if ((data == NULL) || (len == 0))
    {
      debug_printf(DEBUG_NORMAL, "No data available in event!\n");
      return;
    }

  globals = config_get_globals();

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

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

      if (ret <= 0) return;

      intIndex = if_nametoindex(idata->intName);

      if ((ifindex != intIndex) &&
	  (!(TEST_FLAG(wctx->flags, WIRELESS_ONEDOWN))))
	{
	  debug_printf(DEBUG_INT, "Got a wireless event!  Interface index is %d, "
		       "we are using index %d!\n", ifindex, intIndex);
	  debug_printf(DEBUG_INT, "Ignoring!\n");
	  return;
	}
 
      if (TEST_FLAG(idata->flags, WIRELESS_ONEDOWN))
	{
	  if ((ifindex < (intIndex - 1)) || (ifindex > (intIndex)))
	    {
	      debug_printf(DEBUG_INT, "Got a wireless event! Interface index is "
			   "%d, we are using indexes %d & %d!\n", ifindex,
			   intIndex-1, intIndex);
	      return;
	    }
	}

      // Process the event.
      cardif_linux_rtnetlink_process_token(idata, &iwe);
    } while (ret > 0);
}

/*************************************************************************
 *
 *  Manually check and see if we have scan data to return.  This is needed
 * for devices that don't return scan complete events.
 *
 *************************************************************************/
uint8_t cardif_linux_rtnetlink_scancheck(context *ctx)
{
  wireless_ctx *wctx;

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

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

  wctx = (wireless_ctx *)ctx->intTypeData;
  
  if (ctx->intType == ETH_802_11_INT)
    {
      if (TEST_FLAG(wctx->flags, WIRELESS_SCANNING))
	{
	  // It is okay to set a socket of -1 to rtnetlink_check_event.  It
	  // uses an internal variable to keep track of it's socket anyway.
	  if (cardif_linux_rtnetlink_check_event(ctx, -1) != XDATA)
	    {
	      debug_printf(DEBUG_INT, "Waiting for SSID information...\n");
	    }
	  else
	    {
	      // We got data, and canceled our timer, so let the caller know.
#warning Update caller to use the proper value!
	      return 0xff;
	    }
	}
    }
  return 0;
}

/*************************************************************************
 *
 *  Add an attribute to our packet that we are going to send to the kernel.
 *
 *************************************************************************/
int cardif_linux_rtnetlink_add_attr(int type, struct nlmsghdr *nldr,
				    int bufsize, uint8_t *data, int attrlen)
{
  struct rtattr *rtattr = NULL;
  int len = 0;

  // Determine the total length of the message.
  len = RTA_LENGTH(attrlen);

  if (NLMSG_ALIGN(nldr->nlmsg_len)+len > bufsize)
    {
      debug_printf(DEBUG_NORMAL, "Not enough buffer space to create netlink "
		   "request.  Buffer size is %d, but required buffer size "
		   "is %d.\n", bufsize, NLMSG_ALIGN(nldr->nlmsg_len));
      return -1;
    }

  rtattr = (struct rtattr *)(((char *)nldr) + NLMSG_ALIGN(nldr->nlmsg_len));
  rtattr->rta_type = type;
  rtattr->rta_len = len;
  memcpy(RTA_DATA(rtattr), data, attrlen);

  // Update our length to account for everything.
  nldr->nlmsg_len = NLMSG_ALIGN(nldr->nlmsg_len) + len;

  return 0;
}

/*************************************************************************
 *
 *  On init, we need to tell the OS to put interfaces that are "UP" in to
 * dormant mode.  See http://www.flamewarmaster.de/software/operstates.txt
 * for information on how this should all work.
 *
 *************************************************************************/
void cardif_linux_rtnetlink_set_linkmode(context *ctx, uint8_t newstate)
{
  struct {
    struct nlmsghdr nlmsg;
    struct ifinfomsg ifi;
    uint8_t data[sizeof(struct rtattr)+1];
  } state;

  static int seq;

  debug_printf(DEBUG_INT, "Setting Linkmode to %d.\n", newstate);

  memset(&state, 0x00, sizeof(state));

  state.nlmsg.nlmsg_type = RTM_SETLINK;
  state.nlmsg.nlmsg_seq = ++seq;
  state.nlmsg.nlmsg_flags = NLM_F_REQUEST;
  state.nlmsg.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));

  state.ifi.ifi_family = AF_UNSPEC;
  state.ifi.ifi_index = if_nametoindex(ctx->intName);

  if (cardif_linux_rtnetlink_add_attr(IFLA_LINKMODE, &state.nlmsg, 
				      sizeof(state), &newstate, 1) != 0)
    {
      // Couldn't do anything.
      return;
    }

  // Otherwise, send the packet.
  send(rtnl_sock, (void *)&state, sizeof(state), 0);
}

/*************************************************************************
 *
 *  Send an RTNETLINK message that indicates that the interface is now 
 *  fully up.  This will allow things such as DHCP to happen.
 *
 *  See http://www.flamewarmaster.de/software/operstates.txt for information
 *  on how this should all work.
 *
 *************************************************************************/
void cardif_linux_rtnetlink_set_operstate(context *ctx, uint8_t newstate)
{
  struct operstaterequest {
    struct nlmsghdr nlmsg;
    struct ifinfomsg ifi;
    uint8_t data[sizeof(struct rtattr)+1];
  };

  static uint32_t seq;
  
  struct operstaterequest opstate;

  debug_printf(DEBUG_INT, "Setting operstate to %d\n", newstate);

  memset(&opstate, 0x00, sizeof(opstate));

  opstate.nlmsg.nlmsg_type = RTM_SETLINK;
  opstate.nlmsg.nlmsg_seq = ++seq;
  opstate.nlmsg.nlmsg_flags = NLM_F_REQUEST;
  opstate.nlmsg.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));

  opstate.ifi.ifi_family = AF_UNSPEC;
  opstate.ifi.ifi_index = if_nametoindex(ctx->intName);

  if (cardif_linux_rtnetlink_add_attr(IFLA_OPERSTATE, &opstate.nlmsg,
                                      sizeof(opstate), &newstate, 1) != 0)
    {
      // Couldn't do anything.
      return;
    }

  // Otherwise, send the packet.
  send(rtnl_sock, (void *)&opstate, sizeof(opstate), 0);
}

#endif

⌨️ 快捷键说明

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