- 论坛徽章:
- 2
|
回复 11# hellioncu
可以。 /* 只是一个测试程序,测试取到的信息的字节序和值是否正确,arp能否发送出去。*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <linux/if_packet.h>
#include <linux/if_arp.h>
#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/filter.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#define BPF_STMT(code, k) { (unsigned short)(code), 0, 0, k }
#define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
/*
* The instruction encodings.
*/
/* instruction classes */
#define BPF_CLASS(code) ((code) & 0x07)
#define BPF_LD 0x00
#define BPF_LDX 0x01
#define BPF_ST 0x02
#define BPF_STX 0x03
#define BPF_ALU 0x04
#define BPF_JMP 0x05
#define BPF_RET 0x06
#define BPF_MISC 0x07
/* ld/ldx fields */
#define BPF_SIZE(code) ((code) & 0x1
#define BPF_W 0x00
#define BPF_H 0x08
#define BPF_B 0x10
#define BPF_MODE(code) ((code) & 0xe0)
#define BPF_IMM 0x00
#define BPF_ABS 0x20
#define BPF_IND 0x40
#define BPF_MEM 0x60
#define BPF_LEN 0x80
#define BPF_MSH 0xa0
/* alu/jmp fields */
#define BPF_OP(code) ((code) & 0xf0)
#define BPF_ADD 0x00
#define BPF_SUB 0x10
#define BPF_MUL 0x20
#define BPF_DIV 0x30
#define BPF_OR 0x40
#define BPF_AND 0x50
#define BPF_LSH 0x60
#define BPF_RSH 0x70
#define BPF_NEG 0x80
#define BPF_JA 0x00
#define BPF_JEQ 0x10
#define BPF_JGT 0x20
#define BPF_JGE 0x30
#define BPF_JSET 0x40
#define BPF_SRC(code) ((code) & 0x0
#define BPF_K 0x00
#define BPF_X 0x08
int g_ArpSocketId = -1;
char g_cSocketArpSndBuf[64] = {0};
char g_cLocalMac[6] = {0};
int g_dwLocalIpv4 = 0;
struct sockaddr_ll g_ArpSocketAddr = {0};
typedef struct
{
struct arphdr arp;
unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
unsigned char ar_sip[4]; /* sender IP address */
unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
unsigned char ar_tip[4]; /* target IP address */
}STARPHEAD, *PSTARPHEAD;
int Arp_CreateArpRawSocket()
{
int dwSocketId = -1;
int dwRcvBufSize = 64 * 1024; /* 64K */
unsigned int ulSocketFlags;
int dwIfNum = 0;
char cLoop = 0;
int dwInterfaceIndex = -1;
struct ifconf stIfConf = {0};
struct sockaddr_ll stSocketLink = {0};
struct ifreq *pstIfReq = NULL;
static struct sock_filter aFilterProto[]= {
BPF_STMT(BPF_LD+BPF_H+BPF_ABS,12), /* 加载以太网帧头偏移12 字节处的half ( 16 bit) 个bits 到累加器中*/
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K,0x806,0,1), /* 如累加器的值(eth-type)为0x806,则pc + 0,否则pc + 1*/
BPF_STMT(BPF_RET+BPF_K,-1), /* 返回并保留整个包( 这个包是要被扔给上层去处理的)*/
BPF_STMT(BPF_RET+BPF_K,0) /* 返回并丢弃这个包*/
};
static struct sock_fprog aProgram = {.len=sizeof(aFilterProto)/sizeof(aFilterProto[0]), .filter = aFilterProto };
dwSocketId = socket( PF_PACKET, SOCK_RAW, htonl( ETH_P_ARP ) );
if ( dwSocketId < 0 )
{
printf( "[sockttest.c %d]Create socket failed.", __LINE__ );
return -1;
}
ulSocketFlags = fcntl( dwSocketId, F_GETFL, 0 ); /* ~(O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC) */
if ( ulSocketFlags < 0 )
{
printf( "[sockttest.c %d]get socket flags failed.\n", __LINE__ );
close( dwSocketId );
return -1;
}
/* Set socket to non-block mode. */
if ( fcntl( dwSocketId, F_SETFL, O_NONBLOCK | ulSocketFlags ) < 0 )
{
printf( "[sockttest.c %d]set socket non-block mode flags failed.\n", __LINE__ );
close( dwSocketId );
return -1;
}
stIfConf.ifc_len = 128 * sizeof(struct ifreq);
stIfConf.ifc_buf = malloc(stIfConf.ifc_len);
if ( NULL == stIfConf.ifc_buf )
{
printf( "[sockttest.c %d]malloc mem failed.\n", __LINE__ );
return -1;
}
if ( ioctl(dwSocketId, SIOCGIFCONF, &stIfConf) >= 0 )
{
dwIfNum = stIfConf.ifc_len / sizeof( struct ifreq);
}
else
{
printf( "[sockttest.c %d]get netIf-config failed.\n", __LINE__ );
free(stIfConf.ifc_buf);
return -1;
}
for( cLoop = 0; cLoop < dwIfNum; cLoop++ )
{
pstIfReq = (struct ifreq *)stIfConf.ifc_buf + cLoop;
if ( !strcmp( pstIfReq->ifr_name, "eth0" )
{
dwInterfaceIndex = pstIfReq->ifr_ifindex;
/* 获取硬件地址*/
pstIfReq->ifr_hwaddr.sa_family = ARPHRD_ETHER;
if ( 0 > ioctl(dwSocketId, SIOCGIFHWADDR, pstIfReq) )
{
printf( "[sockttest.c %d]get hw-addr failed.\n", __LINE__ );
close( dwSocketId );
free(stIfConf.ifc_buf);
return -1;
}
break;
}
}
if ( cLoop >= dwIfNum )
{
printf( "[sockttest.c %d]can not find Interface called \"eth0\".\n", __LINE__ );
free(stIfConf.ifc_buf);
return -1;
}
stSocketLink.sll_family = PF_PACKET; /* AF_PACKET 等价于PF_PACKET */
stSocketLink.sll_ifindex = dwInterfaceIndex;
stSocketLink.sll_hatype = ARPHRD_ETHER;
stSocketLink.sll_pkttype = PACKET_HOST;
stSocketLink.sll_halen = ETH_ALEN;
stSocketLink.sll_protocol = ETH_P_ARP;
g_ArpSocketAddr = stSocketLink;
memset(g_cLocalMac, 0, 6);
memcpy(g_cLocalMac, pstIfReq->ifr_hwaddr.sa_data, 6);
for( short sLoop = 0; sLoop < 6; sLoop++ )
{
printf("\n ------------\n "
printf( "%x %x", g_cLocalMac[sLoop], pstIfReq->ifr_hwaddr.sa_data[sLoop] );
}
printf("\nindex: %d\n", stSocketLink.sll_ifindex);
if ( 0 > ioctl(dwSocketId, SIOCGIFADDR, pstIfReq) )
{
printf( "[sockttest.c %d]get ip-addr failed.\n", __LINE__ );
close( dwSocketId );
free(stIfConf.ifc_buf);
return -1;
}
g_dwLocalIpv4 = ntohl(((struct sockaddr_in*)&(pstIfReq->ifr_addr))->sin_addr.s_addr);
free(stIfConf.ifc_buf);
if ( bind( dwSocketId, ( struct sockaddr * )&stSocketLink, sizeof(stSocketLink) ) < 0 )
{
printf( "[sockttest.c %d]set socket non-block mode flags failed.\n", __LINE__ );
close( dwSocketId );
return -1;
}
g_ArpSocketId = dwSocketId;
/* Apply the packet filter */
if ( setsockopt(g_ArpSocketId, SOL_SOCKET, SO_ATTACH_FILTER, &aProgram, sizeof(aProgram)) < 0)
{
close( g_ArpSocketId );
printf( "[sockttest.c %d]apply packet filter failed.\n", __LINE__ );
g_ArpSocketId = -1;
return -1;
}
return 0;
}
int Arp_SndArpReq( int dwTargetIp )
{
int dwPktSize = 0;
int dwRet = 0;
struct ethhdr *pstEth = NULL;
struct arphdr *pstArpHdr = NULL;
STARPHEAD *pstArpHead = NULL;
pstEth = (struct ethhdr*)g_cSocketArpSndBuf;
memset(g_cSocketArpSndBuf, 0, 64);
memset( pstEth->h_dest, 0xff, 6 );
memcpy( pstEth->h_source, g_cLocalMac, 6 );
pstEth->h_proto = htons(0x806);
pstArpHdr = (struct arphdr*)((char*)pstEth + sizeof(struct ethhdr));
pstArpHdr->ar_hrd = htons(0x0001);
pstArpHdr->ar_pro = htons(0x800);
pstArpHdr->ar_hln = 6;
pstArpHdr->ar_pln = 4;
pstArpHdr->ar_op = htons(0x0001);
pstArpHead = (STARPHEAD*)(pstArpHdr);
/* sender */
memcpy( pstArpHead->ar_sha, g_cLocalMac, 6 );
*(int*)(pstArpHead->ar_sip) = htonl(g_dwLocalIpv4);
/* target */
memset( pstArpHead->ar_tha, 0x00, 6 );
*(int*)(pstArpHead->ar_tip) = htonl(dwTargetIp);
dwPktSize = sizeof(struct ethhdr) + sizeof(STARPHEAD);
if ( dwPktSize < 64 )
{
dwPktSize = 64;
}
else if ( dwPktSize > 1518 )
{
dwPktSize = 1518;
}
dwRet = sendto( g_ArpSocketId, g_cSocketArpSndBuf, dwPktSize, 0, (struct sockaddr*)&g_ArpSocketAddr, sizeof(g_ArpSocketAddr));
if ( dwRet < 0 )
{
printf( "[sockttest.c %d]send msg failed.\n", __LINE__ );
return -1;
}
return 0;
}
int main()
{
int dwRet = 0;
dwRet = Arp_CreateArpRawSocket();
if (0 != dwRet)
{
printf("[sockttest.c %d]create raw socket failed.\n", __LINE__ );
return 0;
}
dwRet = Arp_SndArpReq(0xc0a80096); /* 192.168.0.150 */
if ( 0 != dwRet )
{
printf("[sockttest.c %d]send arp pkt failed.\n", __LINE__ );
return 0;
}
return 0;
}
|
|