Skip to content

Instantly share code, notes, and snippets.

@bitdust
Created August 28, 2016 15:53
Show Gist options
  • Save bitdust/039dafe5a3cb7f15101c7884b98509a5 to your computer and use it in GitHub Desktop.
Save bitdust/039dafe5a3cb7f15101c7884b98509a5 to your computer and use it in GitHub Desktop.
8021xbridge core file.
/* File: auth.c
* ------------
* 注:核心函数为Authentication(),由该函数执行801.1X认证
*/
int Authentication(const char *DeviceName_1, const char *DeviceName_2);
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <time.h>
#include <stdbool.h>
#include <pcap.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <arpa/inet.h>
#include "debug.h"
const uint8_t BroadcastAddr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; // 广播MAC地址
const uint8_t MultcastAddr[6] = {0x01,0x80,0xc2,0x00,0x00,0x03}; // 多播MAC地址
static void GetMacFromDevice(uint8_t mac[6], const char *devicename);
// From fillmd5.c
extern void FillMD5Area(uint8_t digest[],
uint8_t id, const char passwd[], const uint8_t srcMD5[]);
// From ip.c
extern void GetIpFromDevice(uint8_t ip[4], const char DeviceName[]);
/**
* 函数:Authentication()
*
* 使用以太网进行802.1X认证(802.1X Authentication)
* 该函数将不断循环,转发802.1X认证数据包
*/
int Authentication(const char *DeviceName_1, const char *DeviceName_2)
{
char errbuf_1[PCAP_ERRBUF_SIZE];
pcap_t *adhandle_1; // adapter handle
uint8_t MAC_1[6];
char FilterStr_1[100];
struct bpf_program fcode_1;
char errbuf_2[PCAP_ERRBUF_SIZE];
pcap_t *adhandle_2; // adapter handle
uint8_t MAC_2[6];
char FilterStr_2[100];
struct bpf_program fcode_2;
uint8_t MAC_client[6] = {0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t MAC_switch[6] = {0x00,0x00,0x00,0x00,0x00,0x00};
const int DefaultTimeout=500;//设置接收超时参数,单位ms
// NOTE: 这里没有检查网线是否已插好,网线插口可能接触不良
/* 打开适配器(网卡) */
adhandle_1 = pcap_open_live(DeviceName_1,65536,1,DefaultTimeout,errbuf_1);
if (adhandle_1==NULL) {
fprintf(stderr, "%s\n", errbuf_1);
exit(-1);
}
adhandle_2 = pcap_open_live(DeviceName_2,65536,1,DefaultTimeout,errbuf_2);
if (adhandle_2==NULL) {
fprintf(stderr, "%s\n", errbuf_2);
exit(-1);
}
/* 查询本机MAC地址 */
GetMacFromDevice(MAC_1, DeviceName_1);
GetMacFromDevice(MAC_2, DeviceName_2);
/*
* 设置过滤器:
* 初始情况下只捕获发往本机的802.1X认证会话,不接收多播信息(避免误捕获其他客户端发出的多播信息)
* 进入循环体前可以重设过滤器,那时再开始接收多播信息
*/
sprintf(FilterStr_1, "(ether proto 0x888e)");
pcap_compile(adhandle_1, &fcode_1, FilterStr_1, 1, 0xff);
pcap_setfilter(adhandle_1, &fcode_1);
sprintf(FilterStr_2, "(ether proto 0x888e)");
pcap_compile(adhandle_2, &fcode_2, FilterStr_2, 1, 0xff);
pcap_setfilter(adhandle_2, &fcode_2);
int retcode_1;
int retcode_2;
struct pcap_pkthdr *header_1 = NULL;
const uint8_t *captured_1 = NULL;
struct pcap_pkthdr *header_2 = NULL;
const uint8_t *captured_2 = NULL;
uint8_t sendbuffer_1[500];
uint8_t sendbuffer_2[500];
while(1)
{
retcode_1 = pcap_next_ex(adhandle_1, &header_1, &captured_1);
if (retcode_1==1)
{
memcpy(sendbuffer_1, captured_1, header_1->len);
memcpy(sendbuffer_1+6, MAC_2, 6); // replace source addr
if(captured_1[15] == 0x01)
{ // start.
memcpy(MAC_client, captured_1+6, 6);
printf("set MAC_client. [%2x:%2x:%2x:%2x:%2x:%2x]\n",MAC_client[0],MAC_client[1],MAC_client[2],MAC_client[3],MAC_client[4],MAC_client[5]);
}
else
{
if (MAC_switch[0] == 0x00
&& MAC_switch[1] == 0x00
&& MAC_switch[2] == 0x00
&& MAC_switch[3] == 0x00
&& MAC_switch[4] == 0x00
&& MAC_switch[5] == 0x00)
{
printf("send Multcast to WAN.\n");
memcpy(sendbuffer_1, MultcastAddr, 6);
}
else
{
memcpy(sendbuffer_1, MAC_switch, 6);
}
}
pcap_sendpacket(adhandle_2, sendbuffer_1, header_1->len);
}
retcode_2 = pcap_next_ex(adhandle_2, &header_2, &captured_2);
if (retcode_2==1)
{
memcpy(sendbuffer_2, captured_2, header_2->len);
memcpy(sendbuffer_2+6, MAC_1, 6);
if(captured_2[0] == MAC_2[0]
&& captured_2[1] == MAC_2[1]
&& captured_2[2] == MAC_2[2]
&& captured_2[3] == MAC_2[3]
&& captured_2[4] == MAC_2[4]
&& captured_2[5] == MAC_2[5])
{
memcpy(MAC_switch,captured_2+6,6);
printf("set MAC_switch [%2x:%2x:%2x:%2x:%2x:%2x]\n",MAC_switch[0],MAC_switch[1],MAC_switch[2],MAC_switch[3],MAC_switch[4],MAC_switch[5]);
}
if (MAC_client[0] == 0x00
&& MAC_client[1] == 0x00
&& MAC_client[2] == 0x00
&& MAC_client[3] == 0x00
&& MAC_client[4] == 0x00
&& MAC_client[5] == 0x00)
{
printf("send Multcast to LAN.\n");
memcpy(sendbuffer_2, MultcastAddr, 6);
}
else
{
memcpy(sendbuffer_2, MAC_client, 6);
}
pcap_sendpacket(adhandle_1, sendbuffer_2, header_2->len);
}
}
}
static
void GetMacFromDevice(uint8_t mac[6], const char *devicename)
{
int fd;
int err;
struct ifreq ifr;
fd = socket(PF_PACKET, SOCK_RAW, htons(0x0806));
assert(fd != -1);
assert(strlen(devicename) < IFNAMSIZ);
strncpy(ifr.ifr_name, devicename, IFNAMSIZ);
ifr.ifr_addr.sa_family = AF_INET;
err = ioctl(fd, SIOCGIFHWADDR, &ifr);
assert(err != -1);
memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
err = close(fd);
assert(err != -1);
return;
}
/* File: main.c
* ------------
* 802.1X 转发器
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
/* 子函数声明 */
int Authentication(const char *DeviceName_1, const char *DeviceName_2);
/**
* 函数:main()
*
* 检查程序的执行权限,检查命令行参数格式。
* 允许的调用格式包括:
* njit-client username password
* njit-client username password eth0
* njit-client username password eth1
* 若没有从命令行指定网卡,则默认将使用eth0
*/
int main(int argc, char *argv[])
{
char *DeviceName_1;
char *DeviceName_2;
/* 检查当前是否具有root权限 */
if (getuid() != 0) {
fprintf(stderr, "抱歉,运行本客户端程序需要root权限\n");
fprintf(stderr, "(RedHat/Fedora下使用su命令切换为root)\n");
fprintf(stderr, "(Ubuntu/Debian下在命令前添加sudo)\n");
exit(-1);
}
/* 检查命令行参数格式 */
if (argc<2 || argc>3) {
fprintf(stderr, "命令行参数错误!\n");
fprintf(stderr, "正确的调用格式例子如下:\n");
fprintf(stderr, " %s eth0[LAN] eth1[WAN]\n", argv[0]);
exit(-1);
}
DeviceName_1 = argv[1];
DeviceName_2 = argv[2];
Authentication(DeviceName_1,DeviceName_2);
return (0);
}
#
# Copyright (C) 2006-2008 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=8021xbridge
PKG_RELEASE:=alpha
PKG_VERSION:=0.1
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)-$(PKG_RELEASE)
#its not cool in xd.
#PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
#PKG_MD5SUM:=1b19ac98ba90e18aff7aeefa431753e2
include $(INCLUDE_DIR)/package.mk
define Package/8021xbridge
SECTION:=net
CATEGORY:=Network
TITLE:=802.1X bridge
# URL:=http://liuqun.github.com/njit8021xclient
# WARMING! the code in liuqun's github can't work in xd.
DEPENDS:=+libpcap
PKG_BUILD_DEPENDS:=+libopenssl
endef
define Package/8021xbridge/description
802.1X authentication bridge
Support H3C/iNode's private authentication protocol ALL version.
endef
CONFIGURE_ARGS += \
--program-prefix="8021xbridge-" \
$(NULL)
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./patch/* $(PKG_BUILD_DIR)/
endef
define Build/Configure
$(call Build/Configure/Default)
endef
define Package/8021xbridge/install
$(MAKE) -C $(PKG_BUILD_DIR) install-exec DESTDIR=$(1)
endef
define Package/8021xbridge/conffiles
/etc/config/8021xbridge.conf
endef
$(eval $(call BuildPackage,8021xbridge))
@bitdust
Copy link
Author

bitdust commented Aug 28, 2016

modified from njit8021xclient.
works for ALL version of inode.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment