学习TCP/IP协议,练习使用原始套接字发送数据包。
ARP协议为IP地址到对应的硬件地址之间提供映射。通常ARP请求以广播的形式发送出去,接收到ARP包的主机的IP如果和ARP包中的目的IP一致,则返回一个ARP应答,告知主机的硬件地址。
ARP协议是链路层之上的协议,一般套接字只能处理IP层以上的数据包,访问链路层的数据,就需要使用原始套接字。
能够发送和接收ARP报文的方法大致有三种(不限于这几种):
(1)使用AF_INET协议族中SOCK_PACKET类型的套接字
SOCK_PACKET是Linux支持的一种socket类型,可以通过这种套接字来访问数据链路层,与BPF、DLPI类似。
这种方法要求程序员自己封装ARP包,包括链路层的以太网首部。ARP包的发送和接收与IP层的发送接收类似,不过sockaddr要配置成本地的硬件地址。就像是我们把含以太网首部的数据包封装好,发送到网卡,由网卡根据以太网首部来将数据包在数据链路层上发送出去。
(2)使用AF_PACKET协议族中的SOCK_RAW类型套接字
原始套接字
同样要自己封装含以太网首部的ARP包,但发送地址要配置成数据链路层的地址sockaddr_ll,并且需要跟套接字绑定一下。
(3)使用AF_PACKET协议族中的SOCK_DGRAM类型套接字
该方法与(1)类似,不过不需要自己封装以太网首部。但接受的时候仍能接收到包含以太网首部的ARP应答数据包。
ARP协议的原理大家都清楚,成功实现ARP报文的发送与接收的关键是手动构造ARP报文,调试的时候可以将数据包的信息打印出来,检查构造的数据包是否是合法的ARP报文.
arp.h
view plaincopy to clipboardprint?
#ifndef ARP_H_H_H
#define ARP_H_H_H
#include <linux/if_arp.h>
#pragma pack (1)
struct arp_packet
{
struct ethhdr ethd;
struct arphdr arphd;
unsigned char eth_src_addr[6];
unsigned long inet_src_addr;
unsigned char eth_dst_addr[6];
unsigned long inet_dst_addr;
unsigned char padding[18];
};
#pragma pack ()
void print_ARPMsg(struct arp_packet *packet);
void print_data(unsigned char *buf);
unsigned char* BuildArpRequestPacket(unsigned char* Eth_Src_Addr,unsigned long Inet_Src_Addr,unsigned long Inet_Dst_Addr);
int get_ifindex(char *dev);
#endif
#ifndef ARP_H_H_H
#define ARP_H_H_H
#include <linux/if_arp.h>
#pragma pack (1)
struct arp_packet
{
struct ethhdr ethd;
struct arphdr arphd;
unsigned char eth_src_addr[6];
unsigned long inet_src_addr;
unsigned char eth_dst_addr[6];
unsigned long inet_dst_addr;
unsigned char padding[18];
};
#pragma pack ()
void print_ARPMsg(struct arp_packet *packet);
void print_data(unsigned char
*buf);
unsigned char* BuildArpRequestPacket(unsigned char* Eth_Src_Addr,unsigned long Inet_Src_Addr,unsigned long Inet_Dst_Addr);
int get_ifindex(char *dev);
#endif
arp.c
view plaincopy to clipboardprint?
#include <sys/socket.h>
#include "arp.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/ioctl.h>
void print_ARPMsg(struct arp_packet *packet)
{
unsigned char *mac;
struct in_addr ip;
printf("Source MAC\t\tSource IP\t\tDestinate MAC\t\tDestinate IP\n");
mac = packet->eth_src_addr;
ip.s_addr = packet->inet_src_addr;
printf("%.2X:%.2X:%.2X:%.2X:%.2X:%.2X\t", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
printf("%s\t\t", inet_ntoa(ip));
mac = packet->eth_dst_addr;
ip.s_addr = packet->inet_dst_addr;
printf("%.2X:%.2X:%.2X:%.2X:%.2X:%.2X\t", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
printf("%s\n", inet_ntoa(ip));
}
void print_data(unsigned char *buf)
{
int i;
if(buf != NULL)
{
for(i=0; i<60 ; i++)
{
if( i!=0 && i%16==0 )
fprintf(stdout,"\n" );
fprintf(stdout," %02X", buf[i]);
}
fprintf(stdout, "\n");
}
}
unsigned char* BuildArpRequestPacket(unsigned char* Eth_Src_Addr,
unsigned long Inet_Src_Addr,unsigned long Inet_Dst_Addr)
{
static struct arp_packet packet;
memset (hd.h_dest, 0xff, ETH_ALEN);
memcpy (hd.h_source, Eth_Src_Addr, ETH_ALEN);
memset (&(packet.arphd), 0, sizeof (struct arphdr));
packet.arphd.ar_hrd = htons (ARPHRD_ETHER);
packet.arphd.ar_pro = htons (ETH_P_IP);
packet.arphd.ar_hln = ETH_ALEN; /* 6 */
packet.arphd.ar_pln = 4;
packet.arphd.ar_op = htons (ARPOP_REQUEST);
h_src_addr, Eth_Src_Addr, 6);
packet.inet_src_addr = Inet_Src_Addr;
h_dst_addr, 0, 6);
packet.inet_dst_addr = Inet_Dst_Addr;
memset(packet.padding, 0, 18);
return (unsigned char*)&packet;
}
int get_local_mac(char *dev, unsigned char *mac)
{
int s = socket(AF_INET, SOCK_DGRAM, 0);
struct ifreq req;
int err;
strcpy(req.ifr_name, dev);
err = ioctl(s, SIOCGIFHWADDR, &req);
close(s);
if (err == -1)
return err;
memcpy(mac, req.ifr_hwaddr.sa_data,6);
return 0;
}
unsigned long get_local_ip(char *dev)
{
int s;
struct ifreq req;
int err;
strcpy(req.ifr_name, dev);
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("socket()");
exit(1);
}
err = ioctl(s, SIOCGIFADDR, &req);
close(s);
if (err == -1)
return err;
return ((struct sockaddr_in*)&req.ifr_addr)->sin_addr.s_addr;
}
int get_ifindex(char *dev)
{
int s;
struct ifreq req;
int err;
strcpy(req.ifr_name, dev);
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("socket()");
exit(1);
}
err = ioctl(s, SIOCGIFINDEX, &req);
close(s);
if (err == -1)
return err;
return req.ifr_ifindex;
}
#include <sys/socket.h>
#include "arp.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/ioctl.h>
void print_ARPMsg(struct arp_packet *packet)
{
unsigned char *mac;
struct in_addr ip;
printf("Source MAC\t\tSource IP\t\tDestinate MAC\t\tDestinate IP\n");
mac = packet->eth_src_addr;
ip.s_addr = packet->inet_src_addr;
printf("%.2X:%.2X:%.2X:%.2X:%.2X:%.2X\t", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
printf("%s\t\t", inet_ntoa(ip));
mac = packet->eth_dst_addr;
ip.s_addr = packet->inet_dst_addr;
printf("%.2X:%.2X:%.2X:%.2X:%.2X:%.2X\t", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
printf("%s\n", inet_ntoa(ip));
}
void print_data(unsigned char *buf)
{
int i;
if(buf != NULL)
{
for(i=0; i<60 ; i++)
{
if( i!=0 && i%16==0 )
fprintf(stdout,"\n" );
fprintf(stdout," %02X", buf[i]);
}
fprintf(stdout, "\n");
}
}
unsigned char* BuildArpRequestPacket(unsigned char* Eth_Src_Addr,
unsigned long Inet_Src_Addr,unsigned long Inet_Dst_Addr)
{
static struct arp_packet packet;
memset (hd.h_dest, 0xff, ETH_ALEN);
memcpy (hd.h_source, Eth_Src_Addr, ETH_ALEN);
memset (&(packet.arphd), 0, sizeof (struct arphdr));
packet.arphd.ar_hrd = htons (ARPHRD_ETHER);
packet.arphd.ar_pro = htons (ETH_P_IP);
packet.arphd.ar_hln = ETH_ALEN; /* 6 */
packet.arphd.ar_pln = 4;
packet.arphd.ar_op = htons (ARPOP_REQUEST);
h_src_addr, Eth_Src_Addr, 6);
packet.inet_src_addr = Inet_Src_Addr;
h_dst_addr, 0, 6);
packet.inet_dst_addr = Inet_Dst_Addr;
memset(packet.padding, 0, 18);
return (unsigned char*)&packet;
}
int get_local_mac(char *dev, unsigned char *mac)
{
int s = socket(AF_INET, SOCK_DGRAM, 0);
struct ifreq req;
int err;
strcpy(req.ifr_name, dev);
err = ioctl(s, SIOCGIFHWADDR, &req);
close(s);
if (err == -1)
return err;
memcpy(mac, req.ifr_hwaddr.sa_data,6);
return 0;
}
unsigned long get_local_ip(char *dev)
{
int s;
struct ifreq req;
int err;
strcpy(req.ifr_name, dev);
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("socket()");
exit(1);
}
err = ioctl(s, SIOCGIFADDR, &
req);
close(s);
if (err == -1)
return err;
return ((struct sockaddr_in*)&req.ifr_addr)->sin_addr.s_addr;
}
int get_ifindex(char *dev)
{
int s;
struct ifreq req;
int err;
strcpy(req.ifr_name, dev);
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("socket()");
exit(1);
}
err = ioctl(s, SIOCGIFINDEX, &req);
close(s);
if (err == -1)
return err;
return req.ifr_ifindex;
}
view plaincopy to clipboardprint?
#include <sys/socket.h>
#include "arp.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_ll my_etheraddr;
unsigned char *pktbuf;
unsigned char ackbuf[60];
unsigned char my_mac[6];
unsigned long my_ip;
int my_ifindex;
int nfound;
struct timeval time_out;
fd_set readset,writeset;
if (argc != 3)
{
printf("Usage:%s ifname ip\n");
exit(-1);
}
get_local_mac(argv[1], my_mac);
my_ip = get_local_ip(argv[1]);
/*
* Create sockaddr_ll( link layer ) struct
*/
memset(&my_etheraddr, 0, sizeof(my_etheraddr));
my_etheraddr.sll_family = AF_PACKET;
my_etheraddr.sll_protocol = htons(ETH_P_ARP);
my_etheraddr.sll_ifindex = get_ifindex(argv[1]);
/*
* Create pf_packet socket
*/
sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
if (sockfd < 0)
{
perror("socket");
exit(-1);
}
// bind
if (bind(sockfd, (struct sockaddr*)&my_etheraddr, sizeof(my_etheraddr)))
{
perror("bind");
exit(-1);
}
/*
* Build arp packet
*/
pktbuf = BuildArpRequestPacket(my_mac, my_ip, inet_addr(argv[2]));
printf("Send ARP packet:\n");
print_data(pktbuf);
print_ARPMsg((struct arp_packet*)pktbuf);
if (sendto(sockfd, pktbuf, 80, 0, (struct sockaddr *)&my_etheraddr,sizeof(my_etheraddr)) <= 0)
{
perror("sendto");
exit(-1);
}
/*
* Receive arp packet
*/
// set timeout value
time_out.tv_sec = 3;
time_out.tv_usec = 0;
FD_ZERO( &readset );
FD_ZERO( &writeset );
FD_SET( sockfd,&readset );
nfound = select( sockfd+1,&readset,&writeset,NULL,&time_out );
if (nfound <= 0)
{
printf("Can't connect to %s\n", argv[2]);
exit(-1);
}
recvfrom (sockfd, ackbuf, 60, 0, NULL, 0);
printf("Receive ARP packet:\n");
print_data(ackbuf);
print_ARPMsg((struct arp_packet*)ackbuf);
close(sockfd);
exit(0);
}
#include <sys/socket.h>
#include "arp.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
socket通信报文格式int sockfd;
struct sockaddr_ll my_etheraddr;
unsigned char *pktbuf;
unsigned char ackbuf[60];
unsigned char my_mac[6];
unsigned long my_ip;
int my_ifindex;
int nfound;
struct timeval time_out;
fd_set readset,writeset;
if (argc != 3)
{
printf("Usage:%s ifname ip\n");
exit(-1);
}
get_local_mac(argv[1], my_mac);
my_ip = get_local_ip(argv[1]);
/*
* Create sockaddr_ll( link layer ) struct
*/
memset(&my_etheraddr, 0, sizeof(my_etheraddr));
my_etheraddr.sll_family = AF_PACKET;
my_etheraddr.sll_protocol = htons(ETH_P_ARP);
my_etheraddr.sll_ifindex = get_ifindex(argv[1]);
/*
* Create pf_packet socket
*/
sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
if (sockfd < 0)
{
perror("socket");
exit(-1);
}
// bind
if (bind(sockfd, (struct sockaddr*)&my_etheraddr, sizeof(my_etheraddr)))
{
perror("bind");
exit(-1);
}
/*
* Build arp packet
*/
pktbuf = BuildArpRequestPacket(my_mac, my_ip, inet_addr(argv[2]));
printf("Send ARP packet:\n");
print_data(pktbuf);
print_ARPMsg((struct arp_packet*)pktbuf);
if (sendto(sockfd, pktbuf, 80, 0, (struct sockaddr *)&my_etheraddr,sizeof(my_etheraddr)) <= 0)
{
perror("sendto");
exit(-1);
}
/*
* Receive arp packet
*/
// set timeout value
time_out.tv_sec = 3;
time_out.tv_usec = 0;
FD_ZERO( &readset );
FD_ZERO( &writeset );
FD_SET( sockfd,&readset );
nfound = select( sockfd+1,&readset,&writeset,NULL,&time_out );
if (nfound <= 0)
{
printf("Can't connect to %s\n", argv[2]);
exit(-1);
}
recvfrom (sockfd, ackbuf, 60, 0, NULL, 0);
printf("Receive ARP packet:\n");
print_data(ackbuf);
print_ARPMsg((struct arp_packet*)ackbuf);
close(sockfd);
exit(0);
}
view plaincopy to clipboardprint?
#include <sys/socket.h>
#include "arp.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
int sockfd;
unsigned char *pktbuf;
unsigned char ackbuf[60];
struct sockaddr addr;
unsigned char my_mac[6];
unsigned long my_ip;
int nfound;
struct timeval time_out;
fd_set readset,writeset;
if (argc != 3)
{
printf("Usage:\n");
exit(1);
}
if(get_local_mac(argv[1], my_mac) == -1)
{
perror("get mac");
exit(1);
}
if((my_ip = get_local_ip(argv[1])) == -1)
{
perror("get ip");
exit(1);
}
/*
* Create pf_inet socket
*/
sockfd = socket(PF_IN
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论