cardif_linux.c
来自「linux 下通过802.1认证的安装包」· C语言 代码 · 共 1,995 行 · 第 1/4 页
C
1,995 行
/**
* Linux card interface implementation.
*
* Licensed under a dual GPL/BSD license. (See LICENSE file for more info.)
*
* File: cardif_linux.c
*
* Authors: Chris.Hessing@utah.edu
*
* $Id: cardif_linux.c,v 1.140.2.30 2007/07/21 11:39:12 cgrohmann Exp $
* $Date: 2007/07/21 11:39:12 $
*
**/
#ifdef LINUX_FRAMER
#define _GNU_SOURCE
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/compiler.h>
#include <iwlib.h>
#include <linux/if_packet.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <linux/rtnetlink.h>
#include <string.h>
#include "wireless_copy.h"
#include "xsupconfig.h"
#include "context.h"
#include "config_ssid.h"
#include "cardif/linux/cardif_linux_wext.h"
#include "cardif/cardif.h"
#include "xsup_common.h"
#include "xsup_debug.h"
#include "xsup_err.h"
#include "snmp.h"
#include "statemachine.h"
#include "wireless_sm.h"
#include "cardif/linux/cardif_linux.h"
#include "cardif/linux/cardif_linux_rtnetlink.h"
#include "ipc_events.h"
#include "ipc_events_index.h"
#include "timer.h"
#include "event_core.h"
#include "eapol.h"
#include "interfaces.h"
#ifdef USE_EFENCE
#include <efence.h>
#endif
#ifndef ETH_P_EAPOL
#define ETH_P_EAPOL 0x888e
#endif
// Define this, so the compiler doesn't complain.
extern unsigned int if_nametoindex(const char *);
// This contains a pointer to the functions needed for wireless.
struct cardif_funcs *wireless;
// Store values about what state our interface was in before we start messing
// with it.
struct int_starting_data *startup;
/**
* \brief Get the MAC address of an interface based on it's name.
*
* @param[in] intname A string that contains the interface name that we
* want to get the MAC address for.
*
* @param[out] intmac The interface MAC address of the interface named by
* intname.
*
* \retval XEGENERROR on general error
* \retval XENONE on success
**/
int get_mac_by_name(char *intname, char *intmac)
{
struct ifreq ifr;
struct lin_sock_data *sockData = NULL;
int retval = XENONE;
context *ctx = NULL;
if (!xsup_assert((ctx != NULL), "ctx != NULL", FALSE))
return XEMALLOC;
ctx = event_core_get_active_ctx();
sockData = ctx->sockData;
memset(&ifr, 0x00, sizeof(ifr));
if (strlen(intname) == 0)
{
debug_printf(DEBUG_NORMAL, "Invalid interface name in %s():%d\n",
__FUNCTION__, __LINE__);
return XEGENERROR;
}
ifr.ifr_ifindex = if_nametoindex(intname);
// Tell the ifreq struct which interface we want to use.
Strncpy((char *)&ifr.ifr_name, sizeof(ifr.ifr_name), intname, strlen(intname)+1);
// Get our MAC address.
retval = ioctl(sockData->sockInt, SIOCGIFHWADDR, &ifr);
if (retval < 0)
{
debug_printf(DEBUG_NORMAL, "Error getting hardware (MAC) address for "
"interface %s!\n", intname);
debug_printf(DEBUG_NORMAL, "Error was (%d) : %s\n", errno, strerror(errno));
}
memcpy(intmac, (char *)&ifr.ifr_hwaddr.sa_data[0], 6);
return XENONE;
}
/**
* Clear all keys, and accept unencrypted traffic again.
*
* @param[in] ctx The context that contains the interface that we want
* to allow unencrypted traffic on again.
**/
void cardif_linux_clear_keys(context *ctx)
{
int i;
if (!xsup_assert((ctx != NULL), "ctx != NULL", FALSE))
return;
debug_printf(DEBUG_INT, "Clearing keys!\n");
debug_printf(DEBUG_INT, "Allowing unencrypted frames again.\n");
cardif_drop_unencrypted(ctx, 0);
// Clear the PTK.
debug_printf(DEBUG_INT, "Clearing PTK.\n");
cardif_delete_key(ctx, 0, 1);
for (i=0;i<4;i++)
{
debug_printf(DEBUG_INT, "Clearing key index %d.\n", i);
cardif_delete_key(ctx, i, 0);
}
cardif_linux_wext_enc_disable(ctx);
}
/**
* \brief Determine if we are currently associated.
*
* @param[in] ctx The context that contains the interface that we want to
* check the association status on.
*
* \retval XEMALLOC on error
* \retval IS_UNASSOCIATED when the interface isn't associated
* \retval IS_ASSOCIATED when the interface is associated
**/
int cardif_check_associated(context *ctx)
{
char newmac[6], curbssid[6];
if (!xsup_assert((ctx != NULL), "ctx != NULL", FALSE))
return XEMALLOC;
// If we are wired, this function doesn't do anything useful.
if (ctx->intType != ETH_802_11_INT) return XENONE;
cardif_GetBSSID(ctx, curbssid);
memset(newmac, 0x00, 6);
if (memcmp(newmac, curbssid, 6) == 0)
{
return IS_UNASSOCIATED;
}
memset(newmac, 0x44, 6);
if (memcmp(newmac, curbssid, 6) == 0)
{
return IS_UNASSOCIATED;
}
memset(newmac, 0xFF, 6);
if (memcmp(newmac, curbssid, 6) == 0)
{
return IS_UNASSOCIATED;
}
//Otherwise, we are associated.
return IS_ASSOCIATED;
}
/**
* \brief Set up the wireless cardif_funcs structure to the driver that the
* user has requested.
*
* @param[in] driver A number that identifies the driver that we want to use.
**/
void cardif_set_driver(char driver)
{
switch (driver)
{
case DRIVER_NONE:
wireless = NULL;
break;
default:
case DRIVER_WEXT:
wireless = &cardif_linux_wext_driver;
break;
}
}
/**
* \breif Initialize an interface.
*
* Do whatever is needed to get the interface in to a state that we can send
* and recieve frames on the network. Any information that we need to later
* use should be stored in the context structure.
*
* @param[in] ctx The context that contains enough information for us to
* init the interface.
* @param[in] driver A number that identifies the driver that this card is
* using.
*
* \retval XEMALLOC on memory allocation error
* \retval XEGENERROR on general error
* \retval XENONE on success
**/
int cardif_init(context *ctx, char driver)
{
struct ifreq ifr;
struct lin_sock_data *sockData;
int retval;
struct config_globals *globals;
if (!xsup_assert((ctx != NULL), "ctx != NULL", FALSE))
return XEMALLOC;
// Get the information about the global settings from the config file.
globals = config_get_globals();
if (!xsup_assert((globals != NULL), "globals != NULL", FALSE))
return XEGENERROR;
debug_printf(DEBUG_INT, "Initializing socket for interface %s..\n",
ctx->intName);
// Keep track of which driver we were assigned.
#warning The below needs to be moved to the wireless context init function!
// ctx->driver_in_use = driver;
// Allocate memory for the things we need.
ctx->sockData = (void *)Malloc(sizeof(struct lin_sock_data));
if (ctx->sockData == NULL)
{
debug_printf(DEBUG_NORMAL, "Error allocating memory!\n");
return XEMALLOC;
}
sockData = ctx->sockData;
// Establish a socket handle.
sockData->sockInt = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_EAPOL));
if (sockData->sockInt < 0)
{
debug_printf(DEBUG_NORMAL,
"Couldn't initialize raw socket for interface %s!\n",
ctx->intName);
return XENOSOCK;
}
// Build our link layer socket struct, so we can bind it to a specific
// interface.
sockData->sll.sll_family = PF_PACKET;
sockData->sll.sll_ifindex = if_nametoindex(ctx->intName);
sockData->sll.sll_protocol = htons(ETH_P_EAPOL);
// Bind to the interface.
retval = bind(sockData->sockInt, (const struct sockaddr *)&sockData->sll,
sizeof(struct sockaddr_ll));
if (retval < 0)
{
debug_printf(DEBUG_NORMAL, "Error binding raw socket to interface %s!\n",
ctx->intName);
return XESOCKOP;
}
memset(&ifr, 0x00, sizeof(ifr));
if (strlen(ctx->intName) == 0)
{
debug_printf(DEBUG_NORMAL, "Invalid interface name in %s():%d\n",
__FUNCTION__, __LINE__);
return XEGENERROR;
}
ifr.ifr_ifindex = if_nametoindex(ctx->intName);
// Tell the ifreq struct which interface we want to use.
Strncpy((char *)&ifr.ifr_name, sizeof(ifr.ifr_name), ctx->intName,
strlen(ctx->intName)+1);
// Get our MAC address. (Needed for sending frames out correctly.)
retval = ioctl(sockData->sockInt, SIOCGIFHWADDR, &ifr);
if (retval < 0)
{
debug_printf(DEBUG_NORMAL, "Error getting hardware (MAC) address for interface %s!\n",
ctx->intName);
debug_printf(DEBUG_NORMAL, "Error was (%d) : %s\n", errno, strerror(errno));
return XENOTINT;
}
// Store a copy of our source MAC for later use.
memcpy((char *)&ctx->source_mac[0], (char *)&ifr.ifr_hwaddr.sa_data[0], 6);
// Check if we want ALLMULTI mode, and enable it.
if (TEST_FLAG(globals->flags, CONFIG_GLOBALS_ALLMULTI))
{
if (strlen(ctx->intName) == 0)
{
debug_printf(DEBUG_NORMAL, "Invalid interface name in %s():%d\n",
__FUNCTION__, __LINE__);
return XEGENERROR;
}
// Tell the ifreq struct which interface we want to use.
Strncpy((char *)&ifr.ifr_name, sizeof(ifr.ifr_name), ctx->intName,
strlen(ctx->intName)+1);
if (ioctl(sockData->sockInt, SIOCGIFFLAGS, &ifr) < 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't determine if ALLMULTI is enabled!\n");
} else {
if (ifr.ifr_flags & IFF_ALLMULTI)
{
debug_printf(DEBUG_INT, "Allmulti mode is already enabled on this device!\n");
ctx->flags |= ALLMULTI;
} else {
debug_printf(DEBUG_INT, "Allmulti is currently disabled on this device!\n");
ctx->flags &= ~ALLMULTI;
}
}
debug_printf(DEBUG_INT, "Turning on ALLMULTI mode.\n");
ifr.ifr_flags |= IFF_ALLMULTI;
if (ioctl(sockData->sockInt, SIOCSIFFLAGS, &ifr) < 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't set ALLMULTI mode on this interface! We will continue anyway!\n");
}
}
// Set up wireless card drivers.
cardif_set_driver(driver);
if (cardif_int_is_wireless(ctx) == TRUE)
{
debug_printf(DEBUG_INT, "Interface is wireless.\n");
ctx->intType = ETH_802_11_INT;
if (context_create_wireless_ctx((wireless_ctx **)&ctx->intTypeData, 0) != XENONE)
{
debug_printf(DEBUG_NORMAL, "Couldn't create wireless context for "
"interface!\n");
ipc_events_error(ctx, IPC_EVENT_ERROR_CANT_CREATE_WIRELESS_CTX, ctx->desc);
return -1;
}
// If we have our destination set to AUTO, then preset our destination
// address.
if (globals->destination == DEST_AUTO)
{
cardif_GetBSSID(ctx, ctx->dest_mac);
}
ctx->intType = ETH_802_11_INT;
}
ctx->sendframe = Malloc(FRAMESIZE);
if (ctx->sendframe == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store frames "
"to be sent.\n");
return XEMALLOC;
}
// Initialize our rtnetlink event handler.
cardif_linux_rtnetlink_init(ctx);
event_core_register(cardif_get_socket(ctx), ctx, eapol_withframe,
LOW_PRIORITY, "frame handler");
return XENONE;
}
/**
* \brief Tell the wireless card to start scanning for wireless networks.
*
* @param[in] ctx The context that contains the interface that we want to
* start scanning for networks.
* @param[in] passive TRUE if we want to do a passive scan.
*
* \retval XEMALLOC on memory allocation error
* \retval XENONE on success (or nothing to do)
**/
int cardif_do_wireless_scan(context *ctx, char passive)
{
wireless_ctx *wctx = NULL;
if (!xsup_assert((ctx != NULL), "ctx != NULL", FALSE))
return XEMALLOC;
if (!xsup_assert((ctx->intTypeData != NULL), "ctx->intTypeData != NULL",
FALSE))
return XEMALLOC;
if (wireless == NULL)
{
debug_printf(DEBUG_INT, "No valid wireless calls struct! (%s:%d)\n",
__FUNCTION__, __LINE__);
return XEMALLOC;
}
if (wireless->scan == NULL)
{
debug_printf(DEBUG_NORMAL, "No scan function defined!\n");
return XEMALLOC;
}
wctx = (wireless_ctx *)ctx->intTypeData;
// If we are already scanning, then we shouldn't get here, but go ahead
// and ignore it anyway.
if (TEST_FLAG(wctx->flags, WIRELESS_SCANNING) )
{
debug_printf(DEBUG_INT, "Got a request to start a new scan when one is"
" already in progress! Ignoring!\n");
return XENONE;
}
SET_FLAG(wctx->flags, WIRELESS_SCANNING);
config_ssid_clear(wctx);
return wireless->scan(ctx, passive);
}
/**
* \brief Send a disassociate message.
*
* @param[in] ctx The context that contains the interface that we want
* to send a disassociate message with.
* @param[in] reason_code The reason for the disassociation. (Reason codes
* are specified in the 802.11 standards.)
*
* \retval XEMALLOC on memory allocation error
* \retval XENONE on success
**/
int cardif_disassociate(context *ctx, int reason_code)
{
if (!xsup_assert((ctx != NULL), "ctx != NULL", FALSE))
return XEMALLOC;
if (wireless == NULL) return XEMALLOC;
if (wireless->disassociate == NULL) return XEMALLOC;
debug_printf(DEBUG_INT, "Called %s\n", __FUNCTION__);
return wireless->disassociate(ctx, reason_code);
}
/**
* \brief Return the socket number for functions that need it.
*
* @param[in] ctx The context that contains the socket number we are
* looking for.
*
* \retval XEMALLOC on memory allocation error
* \retval XENONE on success
**/
int cardif_get_socket(context *ctx)
{
struct lin_sock_data *sockData;
if (!xsup_assert((ctx != NULL), "ctx != NULL", FALSE))
return XEMALLOC;
sockData = ctx->sockData;
return sockData->sockInt;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?