标签:
转载 |
分类: linux |
如何从链路层直接发送数据帧
点击(此处)折叠或打开
-
#include
<stdio.h> -
#include
<stdlib.h> -
#include
<string.h> -
#include
<unistd.h> -
#include
<errno.h> -
#include
<sys/socket.h> -
#include
<sys/ioctl.h> -
#include
<sys/types.h> -
#include
<netinet/in.h> -
#include
<netinet/ip.h> -
#include
<netinet/if_ether.h> -
#include
<net/if_arp.h> -
#include
<netpacket/packet.h>
-
#include
<net/if.h> -
#include
<net/ethernet.h> -
-
#define BUFLEN 42
-
-
int
main(int argc,char** argv){
-
int skfd,n;
-
char buf[BUFLEN]={0}; -
struct ether_header *eth; -
struct ether_arp *arp; -
struct sockaddr_ll toaddr; -
struct in_addr targetIP,srcIP; -
struct ifreq ifr; -
-
unsigned char src_mac[ETH_ALEN]={0}; -
unsigned char dst_mac[ETH_ALEN]={0xff,0xff,0xff,0xff,0xff,0xff}; //全网广播ARP请求 -
if(3 != argc){
-
printf("Usage: %s netdevName dstIPn",argv[0]); -
exit(1); -
} -
-
if(0>(skfd=socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL)))){ -
perror("Create Error"); -
exit(1); -
} -
-
bzero(&toaddr,sizeof(toaddr)); -
bzero(&ifr,sizeof(ifr)); -
strcpy(ifr.ifr_name,argv[1]); -
-
//获取接口索引 -
if(-1 == ioctl(skfd,SIOCGIFINDEX,&ifr)){
-
perror("get dev index error:");
-
exit(1);
-
} -
toaddr.sll_ifindex = ifr.ifr_ifindex;
-
printf("interface Index:%dn",ifr.ifr_ifindex);
-
//获取接口IP地址 -
if(-1 == ioctl(skfd,SIOCGIFADDR,&ifr)){
-
perror("get IP addr error:"); -
exit(1);
-
} -
srcIP.s_addr = ((struct sockaddr_in*)&(ifr.ifr_addr))->sin_addr.s_addr;
-
printf("IP addr:%sn",inet_ntoa(((struct sockaddr_in*)&(ifr.ifr_addr))->sin_addr));
-
-
//获取接口的MAC地址 -
if(-1 == ioctl(skfd,SIOCGIFHWADDR,&ifr)){
-
perror("get dev MAC addr error:"); -
exit(1);
-
} -
-
memcpy(src_mac,ifr.ifr_hwaddr.sa_data,ETH_ALEN); -
printf("MAC :X-X-X-X-X-Xn",src_mac[0],src_mac[1],src_mac[2],src_mac[3],src_mac[4],src_mac[5]); -
-
-
//开始填充,构造以太头部 -
eth=(struct ether_header*)buf; -
memcpy(eth->ether_dhost,dst_mac,ETH_ALEN);
-
memcpy(eth->ether_shost,src_mac,ETH_ALEN);
-
eth->ether_type = htons(ETHERTYPE_ARP);
-
-
//手动开始填充用ARP报文首部 -
arp=(struct arphdr*)(buf+sizeof(struct ether_header)); -
arp->arp_hrd = htons(ARPHRD_ETHER); //硬件类型为以太
-
arp->arp_pro = htons(ETHERTYPE_IP); //协议类型为IP
-
-
//硬件地址长度和IPV4地址长度分别是6字节和4字节 -
arp->arp_hln = ETH_ALEN;
-
arp->arp_pln = 4;
-
-
//操作码,这里我们发送ARP请求 -
arp->arp_op = htons(ARPOP_REQUEST);
-
-
//填充发送端的MAC和IP地址 -
memcpy(arp->arp_sha,src_mac,ETH_ALEN); -
memcpy(arp->arp_spa,&srcIP,4); -
-
//填充目的端的IP地址,MAC地址不用管 -
inet_pton(AF_INET,argv[2],&targetIP);
-
memcpy(arp->arp_tpa,&targetIP,4);
-
-
toaddr.sll_family = PF_PACKET;
-
n=sendto(skfd,buf,BUFLEN,0,(struct sockaddr*)&toaddr,sizeof(toaddr)); -
-
close(skfd); -
return 0; - }
点击(此处)折叠或打开
-
struct ether_header
-
{
-
u_int8_t ether_dhost[ETH_ALEN]; /* destination eth addr */ -
u_int8_t ether_shost[ETH_ALEN]; /* source ether addr */ -
u_int16_t ether_type; /* packet type ID field */ -
}
__attribute__ ((__packed__));
点击(此处)折叠或打开
-
struct arphdr
-
{
-
unsigned short ar_hrd; /* format of hardware address */ -
unsigned short ar_pro; /* format of protocol address */ -
unsigned char ar_hln; /* length of hardware address */ -
unsigned char ar_pln; /* length of protocol address */ -
unsigned short ar_op; /* ARP opcode (command) */ - }
点击(此处)折叠或打开
-
struct ether_arp
{ -
struct arphdr ea_hdr; /* fixed-size 8 bytes header */ -
u_int8_t arp_sha[ETH_ALEN]; /* sender hardware address */ -
u_int8_t arp_spa[4]; /* sender protocol address */ -
u_int8_t arp_tha[ETH_ALEN]; /* target hardware address */ -
u_int8_t arp_tpa[4]; /* target protocol address */ -
};
-
-
#define arp_hrd ea_hdr.ar_hrd
-
#define arp_pro ea_hdr.ar_pro
-
#define arp_hln ea_hdr.ar_hln
-
#define arp_pln ea_hdr.ar_pln
- #define arp_op ea_hdr.ar_op
点击(此处)折叠或打开
-
#include
<stdio.h> -
#include
<stdlib.h> -
#include
<string.h> -
#include
<unistd.h> -
#include
<errno.h> -
#include
<sys/socket.h> -
#include
<sys/ioctl.h> -
#include
<sys/types.h> -
#include
<netinet/in.h> -
#include
<netinet/ip.h> -
#include
<netinet/if_ether.h> -
#include
<net/if_arp.h> -
#include
<netpacket/packet.h>
-
#include
<net/if.h> -
#define BUFLEN 60
-
-
int
main(int argc,char** argv){
-
int i,skfd,n;
-
char buf[ETH_FRAME_LEN]={0}; -
struct ethhdr *eth; -
struct ether_arp *arp; -
struct sockaddr_ll fromaddr; -
struct ifreq ifr; -
-
unsigned char src_mac[ETH_ALEN]={0}; -
-
if(2 != argc){
-
printf("Usage: %s netdevNamen",argv[0]); -
exit(1);
-
}
-
-
//只接收发给本机的ARP报文
-
if(0>(skfd=socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ARP)))){
-
perror("Create Error"); -
exit(1);
-
}
-
-
bzero(&fromaddr,sizeof(fromaddr));
-
bzero(&ifr,sizeof(ifr));
-
strcpy(ifr.ifr_name,argv[1]);
-
-
//获取接口索引
-
if(-1 == ioctl(skfd,SIOCGIFINDEX,&ifr)){
-
perror("get dev index error:"); -
exit(1);
-
}
-
fromaddr.sll_ifindex = ifr.ifr_ifindex;
-
printf("interface Index:%dn",ifr.ifr_ifindex); -
-
//获取接口的MAC地址
-
if(-1 == ioctl(skfd,SIOCGIFHWADDR,&ifr)){
-
perror("get dev MAC addr error:"); -
exit(1);
-
}
-
-
memcpy(src_mac,ifr.ifr_hwaddr.sa_data,ETH_ALEN);
-
printf("MAC :X-X-X-X-X-Xn",src_mac[0],src_mac[1],src_mac[2],src_mac[3],src_mac[4],src_mac[5]); -
-
fromaddr.sll_family = PF_PACKET;
-
fromaddr.sll_protocol=htons(ETH_P_ARP);
-
fromaddr.sll_hatype=ARPHRD_ETHER;
-
fromaddr.sll_pkttype=PACKET_HOST;
-
fromaddr.sll_halen=ETH_ALEN;
-
memcpy(fromaddr.sll_addr,src_mac,ETH_ALEN);
-
-
bind(skfd,(struct sockaddr*)&fromaddr,sizeof(struct sockaddr)); -
-
while(1){
-
memset(buf,0,ETH_FRAME_LEN);
-
n=recvfrom(skfd,buf,ETH_FRAME_LEN,0,NULL,NULL);
-
eth=(struct ethhdr*)buf; -
arp=(struct ether_arp*)(buf+14); -
-
printf("Dest MAC:"); -
for(i=0;i<ETH_ALEN;i++){
-
printf("X-",eth->h_dest[i]);
-
}
-
printf("Sender MAC:"); -
for(i=0;i<ETH_ALEN;i++){
-
printf("X-",eth->h_source[i]);
-
}
-
-
printf("n");
-
printf("Frame type:%0Xn",ntohs(eth->h_proto)); -
-
if(ntohs(arp->arp_op)==2){
-
printf("Get an ARP replay!n"); -
}
-
}
-
close(skfd);
-
return 0; - }