📄 rt61apd.c
字号:
/*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. See README and COPYING for
* more details.
Module Name:
rt61apd.c
Revision History:
Who When What
-------- ---------- ----------------------------------------------
Jan, Lee Dec --2003 modified
*/
#include <stdio.h>
#include <unistd.h>
#include <sched.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <string.h>
#include <features.h>
#include <stdlib.h>
#include <stdarg.h> /* va_start... */
#include <sys/types.h>
#include <pthread.h>
#include <signal.h> /* kill */
#include <malloc.h>
#include <errno.h> /* errno */
#include <sys/stat.h> /* mkdir */
#include <fcntl.h> /* creat */
#include <sys/ipc.h> /* ftok */
#include <sys/sem.h> /* semget */
#include <termios.h> /* tcgetattr, tcsetattr */
#include <net/if_arp.h>
#include <netpacket/packet.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <string.h>
#include <syslog.h>
#include <sys/socket.h>
#include "rt61apd.h"
#include "eloop.h"
#include "ieee802_1x.h"
#include "eapol_sm.h"
#include "ap.h"
#include "sta_info.h"
#include "radius_client.h"
#include "config.h"
#include "mac2port.h"
#include "switch_if.h"
//#define RT61AP_SYSTEM_PATH "/etc/Wireless/RT61AP/RT61AP.dat"
#if MULTIPLE_RADIUS
static void create_pidfile(const char* ifname);
unsigned char wireless_ifname[IFNAMSIZ+1];
#endif
struct hapd_interfaces {
int count;
rtapd **rtapd;
};
#define SWITCH_PIPE_KEY_PATH "/proc/switch"
#define SWITCH_PIPE_PREFIX "/tmp/myfifo"
#define PERMS0 IPC_CREAT|00666
#define PERMS1 IPC_CREAT|IPC_EXCL|00666
#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
/* union semun is defined by including <sys/sem.h> */
#else
/* according to X/OPEN we have to define it ourselves */
union semun {
int val; /* value for SETVAL */
struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* array for GETALL, SETALL */
/* Linux specific part: */
struct seminfo *__buf; /* buffer for IPC_INFO */
};
#endif
static int logsem_p(int semid)
{
struct sembuf sops;
sops.sem_num = 0;
sops.sem_op = -1;
sops.sem_flg = SEM_UNDO;//IPC_NOWAIT;//SEM_UNDO;
if (semop(semid, &sops,1) == -1) {
return 0;
}
return 1;
}
static int logsem_v(int semid)
{
struct sembuf sops;//={0, 1,SEM_UNDO};
sops.sem_num = 0;
sops.sem_op = 1;
sops.sem_flg = SEM_UNDO;//IPC_NOWAIT;//SEM_UNDO;
if (semop(semid, &sops,1) == -1 ) {
return 0;
}
return 1;
}
int switch_cli_pipe_write(char *command)
{
int semid = -1;
union semun sem;
char w_buff[100];
int fd =0;
int nwrite = 0;
semid = semget(ftok(SWITCH_PIPE_KEY_PATH,'y'), 1, PERMS1);
// fprintf(stderr, "\r\n1 ----> switch_cli_pipe_write : semid = %d\n", semid);
if (semid == -1 && EEXIST == errno) {
semid = semget(ftok(SWITCH_PIPE_KEY_PATH,'y'), 1, PERMS0);
} else if (semid >= 0) {
sem.val = 1;
semctl(semid, 0, SETVAL, sem);
}
// fprintf(stderr, "2 ----> switch_cli_pipe_write: semid = %d\n", semid);
logsem_p(semid);
fprintf(stderr, "CMD : %s\n", command);
fd = open(SWITCH_PIPE_PREFIX, O_WRONLY | O_NONBLOCK);
strcpy(w_buff, command);
if((nwrite = write(fd, w_buff, 100)) == -1){
if(errno == EAGAIN)
printf("switch_cli_pipe_write write error \n");
}
else{
printf("switch_cli_pipe_write write OK \n");
}
usleep(50 * 1000);
close(fd);
if (!logsem_v(semid))
{
fprintf(stderr, "can't do sem v operation! \n");
semctl(semid,0,IPC_RMID);
return -1;
}
return 0;
}
void AuthPort_init()
{
char cCmdBuf[256];
memset(cCmdBuf, 0, sizeof(cCmdBuf));
sprintf(cCmdBuf, "auth8021x create\n");
switch_cli_pipe_write(cCmdBuf);
memset(cCmdBuf, 0, sizeof(cCmdBuf));
sprintf(cCmdBuf, "auth init\n");
switch_cli_pipe_write(cCmdBuf);
memset(cCmdBuf, 0, sizeof(cCmdBuf));
sprintf(cCmdBuf, "auth block pbm=0xffffff\n");
switch_cli_pipe_write(cCmdBuf);
}
/*
========================================================================
Routine Description:
Compare two memory block
Arguments:
Adapter Pointer to our adapter
Return Value:
0: memory is equal
1: pSrc1 memory is larger
2: pSrc2 memory is larger
Note:
========================================================================
*/
u16 RTMPCompareMemory(void *pSrc1,void *pSrc2, u16 Length)
{
char *pMem1;
char *pMem2;
u16 Index = 0;
pMem1 = (char*) pSrc1;
pMem2 = (char*) pSrc2;
for (Index = 0; Index < Length; Index++)
{
if (pMem1[Index] > pMem2[Index])
return (1);
else if (pMem1[Index] < pMem2[Index])
return (2);
}
// Equal
return (0);
}
int RT_ioctl(rtapd *rtapd, int param, char *data, int data_len, int lPort)
{
int ret = 1;
int i;
struct sockaddr_ll daddr; //ken_send
daddr.sll_family = AF_PACKET;
daddr.sll_protocol = ETH_P_ALL;
daddr.sll_ifindex = 5;
daddr.sll_hatype = 1;
daddr.sll_halen = 8;
for ( i=0; i<6; i++)
daddr.sll_addr[i] = data[i];
#if 0
char buf[1600];
SWITCH_8021X_PACKET_S *pEapolPacket;
int fd;
#define SWITCH_TX_PIPE "/tmp/protocoltx"
if(RTPRIV_IOCTL_RADIUS_DATA != param)
{
return -1;
}
if((fd = open(SWITCH_TX_PIPE,O_WRONLY)) < 0)
{
fprintf(stderr ," open pipe error \n");
return -1;
}
if (data_len < 60)
{
data_len = 60;
}
pEapolPacket = (SWITCH_8021X_PACKET_S*)buf;
memset(buf, 0, sizeof(buf));
pEapolPacket->lLength = htonl(data_len);
pEapolPacket->lPort = htonl(lPort);
memcpy(pEapolPacket->cPacket, data, data_len);
//fprintf(stderr, "RT_ioctl\n");
ret = write(fd, buf, data_len + 8);
if(ret < 0)
{
fprintf(stderr, "write pipe to switch");
}
close(fd);
#else
if(RTPRIV_IOCTL_RADIUS_DATA != param)
{
return -1;
}
DBGPRINT(RT_DEBUG_INFO,"eth_sock =%d\n",rtapd->eth_sock);
/*for debug*//*begin*/
for(i=0; i<data_len; i++)
{
DBGPRINT(RT_DEBUG_TRACE, "%02x ", data[i]);
}
DBGPRINT(RT_DEBUG_TRACE,"\n");
DBGPRINT(RT_DEBUG_TRACE,"send to (%d)\n",rtapd->eth_sock);
/*for debug*//*end*/
//ken_send
//ret = send(rtapd->eth_sock, data, data_len, 0);
ret=sendto(rtapd->eth_sock, data, data_len, 0x00,(struct sockaddr *)&daddr, sizeof(daddr));
if(ret < 0)
{
DBGPRINT(RT_DEBUG_ERROR, "send[RADIUS]1 errno(%d)\n",errno);
}
#endif
return ret;
}
/*for debug*/
int debugProc = 0;
int Code;
int TypeCode;
char eapol_start[] =
{
0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x03,0x47,0xdf,0x32,0x06,0x88,0x8e,0x01,0x01,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
char *EAP_code[] =
{
"",
"Request",
"Respons",
"Success",
"Failure"
};
/*static int Recv_Eapol(char *pBuf, int lBufLength, int *plLength, int *pSrcPort)
{
if(lBufLength < 1518)
{
return -1;
}
if(debugProc == 0)
{
*plLength = sizeof(eapol_start);
memcpy(pBuf, eapol_start, *plLength);
}
*pSrcPort = 1;
return 0;
}*/
void Recv_Eapol(char *pcBuf, int lPacketLength, int lSrcPort, void *p)
{
priv_rec *rec;
size_t left;
u8 *sa, *pos, *pucPortMac, apidx=0;
u16 ethertype,i;
int lRetVal;
rtapd *rtapd = p;
//fprintf(stderr, " Recv_Eapol\n");
if (lPacketLength < 0)
{
perror("recv");
return;
}
rec = (priv_rec*)pcBuf;
left = lPacketLength - sizeof(*rec) + 1;
if (left <= 0)
{
DBGPRINT(RT_DEBUG_ERROR," too short recv\n");
return;
}
sa = rec->saddr;
ethertype = rec->ethtype[0] << 8;
ethertype |= rec->ethtype[1];
Code = rec->ethtype[2];
if(ethertype == ETH_P_PAE)
{
DBGPRINT(RT_DEBUG_TRACE," Recve a PAEOL packet, %s, Src Port=%d \n",EAP_code[Code], lSrcPort);
DBGPRINT(RT_DEBUG_INFO,"Recv_Eapol :: handle_frame(len=%d) :SRC_MAC %x:%x:%x:%x:%x:%x DST_MAC %x:%x:%x:%x:%x:%x Type=%x \n",
lPacketLength, rec->saddr[0], rec->saddr[1], rec->saddr[2], rec->saddr[3], rec->saddr[4], rec->saddr[5],
rec->daddr[0], rec->daddr[1], rec->daddr[2], rec->daddr[3], rec->daddr[4], rec->daddr[5], ethertype);
apidx = 0;
lRetVal = Mac2Port_FindMacByPort(lSrcPort, &pucPortMac);
if(lRetVal == -1)/*输入参数错误*/
{
return;
}
else if(lRetVal == 1)
{
Mac2Port_AddMac(sa, lSrcPort);
}
else
{
if(0 != memcmp(pucPortMac, sa, 6))
{
fprintf(stderr, "8021x Mac not same in port=%d,SRC_MAC %x:%x:%x:%x:%x:%x DST_MAC %x:%x:%x:%x:%x:%x\n", lSrcPort,
rec->saddr[0], rec->saddr[1], rec->saddr[2], rec->saddr[3], rec->saddr[4], rec->saddr[5],
rec->daddr[0], rec->daddr[1], rec->daddr[2], rec->daddr[3], rec->daddr[4], rec->daddr[5]);
return;
}
}
}
else
return;
pos = rec->xframe;
if (lPacketLength < 52 )
{
DBGPRINT(RT_DEBUG_INFO,"Recv_Eapol :: handle_short_frame: (len=%d, left=%d)\n", lPacketLength,left);
for(i = 0; i < left; i++)
DBGPRINT(RT_DEBUG_INFO," %x", *(pos+i));
DBGPRINT(RT_DEBUG_INFO,"\n");
}
ieee802_1x_receive(rtapd, sa, &apidx, pos, left, ethertype);
}
static void Handle_read(int sock, void *eloop_ctx, void *sock_ctx)
{
rtapd *rtapd = eloop_ctx;
int len,lPacketLength,lSrcPort;
unsigned char buf[2000];
u8 *sa, *pos, *pucPortMac, apidx=0;
u16 ethertype,i;
priv_rec *rec;
size_t left;
int lRetVal;
len = recv(sock, buf, sizeof(buf), 0);
lPacketLength = len;
if (len < 0)
{
perror("recv");
Handle_term(15,eloop_ctx,sock_ctx);
return;
}
rec = (priv_rec*)buf;
left = len - sizeof(*rec)+1;
if (left <= 0)
{
DBGPRINT(RT_DEBUG_ERROR," too short recv\n");
return;
}
sa = rec->saddr;
ethertype = rec->ethtype[0] << 8;
ethertype |= rec->ethtype[1];
Code = rec->ethtype[2];
lSrcPort = buf[len - 1];
if(ethertype == ETH_P_PAE)
{
for (i =0;i< lPacketLength;i++)
DBGPRINT(RT_DEBUG_TRACE,"%02x ",buf[i]);
DBGPRINT(RT_DEBUG_TRACE,"\n");
DBGPRINT(RT_DEBUG_TRACE," Recve a PAEOL packet, %s, Src Port=%d Lentgth=%d \n",EAP_code[Code], lSrcPort, lPacketLength);
DBGPRINT(RT_DEBUG_TRACE,"Recv_Eapol :: handle_frame(len=%d) :SRC_MAC %x:%x:%x:%x:%x:%x DST_MAC %x:%x:%x:%x:%x:%x Type=%x \n",
lPacketLength, rec->saddr[0], rec->saddr[1], rec->saddr[2], rec->saddr[3], rec->saddr[4], rec->saddr[5],
rec->daddr[0], rec->daddr[1], rec->daddr[2], rec->daddr[3], rec->daddr[4], rec->daddr[5], ethertype);
apidx = 0;
lRetVal = Mac2Port_FindMacByPort(lSrcPort, &pucPortMac);
if(lRetVal == -1)/*输入参数错误*/
{
return;
}
else if(lRetVal == 1)
{
Mac2Port_AddMac(sa, lSrcPort);
}
else
{
if(0 != memcmp(pucPortMac, sa, 6))
{
fprintf(stderr, "8021x Mac not same in port=%d,SRC_MAC %x:%x:%x:%x:%x:%x DST_MAC %x:%x:%x:%x:%x:%x\n", lSrcPort,
rec->saddr[0], rec->saddr[1], rec->saddr[2], rec->saddr[3], rec->saddr[4], rec->saddr[5],
rec->daddr[0], rec->daddr[1], rec->daddr[2], rec->daddr[3], rec->daddr[4], rec->daddr[5]);
return;
}
}
}
else
return;
pos = rec->xframe;
if (lPacketLength < 52 )
{
DBGPRINT(RT_DEBUG_INFO,"Recv_Eapol :: handle_short_frame: (len=%d, left=%d)\n", lPacketLength,left);
for(i = 0; i < left; i++)
DBGPRINT(RT_DEBUG_INFO," %x", *(pos+i));
DBGPRINT(RT_DEBUG_INFO,"\n");
}
ieee802_1x_receive(rtapd, sa, &apidx, pos, left, ethertype);
}
int Apd_init_sockets(rtapd *rtapd)
{
struct ifreq ifr;
struct sockaddr_ll addr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -