ARP的C代码实现
来源:互联网 发布:与妻书读后感知乎 编辑:程序博客网 时间:2024/05/16 06:08
<h2 id="t_412ef3420100mvbp" class="titName SG_txta">linux下C语言实现ARP数据包发送</h2>#include <netdb.h>#include <sys/socket.h>#include <sys/types.h>#include <stdio.h>#include <errno.h>#include <sys/ioctl.h>#include <net/if.h>#include <signal.h>#include <netinet/ip.h>#include <netinet/in.h>#include <string.h>#include <arpa/inet.h>#include <netinet/ip_icmp.h>#include <linux/if_ether.h>#define ETH_HW_ADDR_LEN 6#define IP_ADDR_LEN 4#define ARP_FRAME_TYPE 0x0806#define ETHER_HW_TYPE 1#define IP_PROTO_TYPE 0x0800#define OP_ARP_REQUEST 2#define OP_ARP_QUEST 1#define DEFAULT_DEVICE "eth0"char usage[] ={"send_arp: sends out custom ARP packet. ferrysnow@gmail.com \nusage : send_arp src_ip_addr src_hw_addr targ_ip_addr tar_hw_addr number"};struct arp_packet{u_char targ_hw_addr[ETH_HW_ADDR_LEN];u_char src_hw_addr[ETH_HW_ADDR_LEN];u_short frame_type;u_short hw_type;u_short prot_type;u_char hw_addr_size;u_char prot_addr_size;u_short op;u_char sndr_hw_addr[ETH_HW_ADDR_LEN];u_char sndr_ip_addr[IP_ADDR_LEN];u_char rcpt_hw_addr[ETH_HW_ADDR_LEN];u_char rcpt_ip_addr[IP_ADDR_LEN];u_char padding[18];};void die(char*);void get_ip_addr(struct in_addr*, char*);void get_hw_addr(char*, char*);int main(int argc, char* argv[]){ struct in_addr src_in_addr, targ_in_addr; struct arp_packet pkt; struct sockaddr sa; int sock; int j, number; if (argc != 6) { die(usage); } sock = socket(AF_INET, SOCK_PACKET, htons(ETH_P_RARP)); if (sock < 0) { perror("socket"); exit(1); } number = atoi(argv[5]); pkt.frame_type = htons(ARP_FRAME_TYPE); pkt.hw_type = htons(ETHER_HW_TYPE); pkt.prot_type = htons(IP_PROTO_TYPE); pkt.hw_addr_size = ETH_HW_ADDR_LEN; pkt.prot_addr_size = IP_ADDR_LEN; pkt.op = htons(OP_ARP_QUEST); get_hw_addr(pkt.targ_hw_addr, argv[4]); get_hw_addr(pkt.rcpt_hw_addr, argv[4]); get_hw_addr(pkt.src_hw_addr, argv[2]); get_hw_addr(pkt.sndr_hw_addr, argv[2]); get_ip_addr(&src_in_addr, argv[1]); get_ip_addr(&targ_in_addr, argv[3]); memcpy(pkt.sndr_ip_addr, &src_in_addr, IP_ADDR_LEN); memcpy(pkt.rcpt_ip_addr, &targ_in_addr, IP_ADDR_LEN); bzero(pkt.padding, 18); strcpy(sa.sa_data, DEFAULT_DEVICE); for (j = 0; j < number; j++) { if (sendto(sock, &pkt, sizeof(pkt), 0, &sa, sizeof(sa)) < 0) { perror("sendto"); exit(1); } } exit(0);}void die(char* str){ fprintf(stderr, "%s\n", str); exit(1);}void get_ip_addr(struct in_addr* in_addr, char* str){ struct hostent* hostp; in_addr->s_addr = inet_addr(str); if (in_addr->s_addr == -1) { if ((hostp = gethostbyname(str))) { bcopy(hostp->h_addr, in_addr, hostp->h_length); } else { fprintf(stderr, "send_arp: unknown host %s\n", str); exit(1); } }}void get_hw_addr(char* buf, char* str){ int i; char c, val; for (i = 0; i < ETH_HW_ADDR_LEN; i++) { if (!(c = tolower(*str++))) { die("Invalid hardware address"); } if (isdigit(c)) { val = c - '0'; } else if (c >= 'a' && c <= 'f') { val = c - 'a' + 10; } else { die("Invalid hardware address"); } *buf = val << 4; if (!(c = tolower(*str++))) { die("Invalid hardware address"); } if (isdigit(c)) { val = c - '0'; } else if (c >= 'a' && c <= 'f') { val = c - 'a' + 10; } else { die("Invalid hardware address"); } *buf++ |= val; if (*str == ':') { str++; } }}
ARP协议的c语言实现源代码
#include <netdb.h>#include <unistd.h>#include <ctype.h>#include <errno.h>#include <signal.h>#include <string.h>#include <stdio.h>#include <stdlib.h>#include <getopt.h>#include <sys/uio.h>#include <sys/file.h>#include <sys/time.h>#include <sys/signal.h>#include <sys/ioctl.h>#include <sys/param.h>#include <sys/socket.h>#include <linux/sockios.h>#include <linux/if.h>#include <linux/if_arp.h>#include <linux/if_packet.h>#include <linux/types.h>#include <netinet/in.h>#include <arpa/inet.h>#define src_addr "192.168.0.239"#define device "eth0"#define fill_buf "aaaaaaaaaaaa"int socket_id;char *target = src_addr;int send_count = 0;int recv_count = 0;struct in_addr src, dst;struct sockaddr_ll me, he;struct timeval send_time, recv_time;struct in_addr get_src_ip(char * devices){struct sockaddr_in saddr;int sock_id = socket(AF_INET, SOCK_DGRAM, 0);if (sock_id < 0) { perror("socket"); exit(2);}if (devices) { if (setsockopt(sock_id, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device)+1) == -1) perror("WARNING: interface is ignored");}int alen = sizeof(saddr);memset(&saddr, 0, sizeof(saddr));saddr.sin_port = htons(0x1000);saddr.sin_family = AF_INET; if (connect(sock_id, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) { perror("connect"); exit(2);}if (getsockname(sock_id, (struct sockaddr*)&saddr, &alen) == -1) { perror("getsockname"); exit(2);}close(sock_id);return saddr.sin_addr;}int check_device(char* if_dev, int ss){int ifindex;struct ifreq ifr;memset(&ifr, 0, sizeof(ifr));strncpy(ifr.ifr_name, if_dev, IFNAMSIZ-1); if (ioctl(ss, SIOCGIFINDEX, &ifr) < 0) { fprintf(stderr, "arping: unknown iface %s\n", if_dev); exit(2); } ifindex = ifr.ifr_ifindex; if (ioctl(ss, SIOCGIFFLAGS, (char*)&ifr)) { perror("ioctl(SIOCGIFFLAGS)"); exit(2); } if (!(ifr.ifr_flags&IFF_UP)) { printf("Interface \"%s\" is down\n", if_dev); exit(2); } if (ifr.ifr_flags&(IFF_NOARP|IFF_LOOPBACK)) { printf("Interface \"%s\" is not ARPable\n", if_dev); exit(2); }return ifindex;} // check_device()int socket_init(){int s, s_errno;s = socket(PF_PACKET, SOCK_DGRAM, 0);s_errno = errno;me.sll_family = AF_PACKET;me.sll_ifindex = check_device(device, s);me.sll_protocol = htons(ETH_P_ARP);if (bind(s, (struct sockaddr*)&me, sizeof(me)) == -1) { perror("bind"); exit(2); }int alen = sizeof(me);if (getsockname(s, (struct sockaddr*)&me, &alen) == -1) { perror("getsockname"); exit(2);}if (me.sll_halen == 0) { printf("Interface \"%s\" is not ARPable (no ll address)\n", device); exit(2);}he = me;memset(he.sll_addr, -1, he.sll_halen); // set dmac addr FF:FF:FF:FF:FF:FFreturn s;}intcreate_pkt(unsigned char * buf, struct in_addr src, struct in_addr dst, struct sockaddr_ll * FROM, struct sockaddr_ll * TO){struct arphdr *ah = (struct arphdr*) buf;unsigned char *p = (unsigned char *)(ah+1);ah->ar_hrd = htons(FROM->sll_hatype);if (ah->ar_hrd == htons(ARPHRD_FDDI)) ah->ar_hrd = htons(ARPHRD_ETHER);ah->ar_pro = htons(ETH_P_IP);ah->ar_hln = FROM->sll_halen;ah->ar_pln = 4;ah->ar_op = htons(ARPOP_REQUEST);memcpy(p, &FROM->sll_addr, ah->ar_hln);p+=FROM->sll_halen;memcpy(p, &src, 4);p+=4;memcpy(p, &TO->sll_addr, ah->ar_hln);p+=ah->ar_hln;memcpy(p, &dst, 4);p+=4;memcpy(p, fill_buf, strlen(fill_buf) );p+=12;return (p-buf);}void send_pkt(){unsigned char send_buf[256];int pkt_size = create_pkt(send_buf, src, dst, &me, &he);gettimeofday(&send_time, NULL); int cc = sendto(socket_id, send_buf, pkt_size, 0, (struct sockaddr*)&he, sizeof(he));if( cc == pkt_size ) send_count++; alarm(1);}int chk_recv_pkt(unsigned char * buf, struct sockaddr_ll * FROM){struct arphdr *ah = (struct arphdr*)buf;unsigned char *p = (unsigned char *)(ah+1);struct in_addr src_ip, dst_ip;if (ah->ar_op != htons(ARPOP_REQUEST) && ah->ar_op != htons(ARPOP_REPLY)) return 0;if (ah->ar_pro != htons(ETH_P_IP) || ah->ar_pln != 4 || ah->ar_hln != me.sll_halen ) return 0;memcpy(&src_ip, p+ah->ar_hln, 4);memcpy(&dst_ip, p+ah->ar_hln+4+ah->ar_hln, 4);if (src_ip.s_addr != dst.s_addr || src.s_addr != dst_ip.s_addr ) return 0;return (p-buf);}void disp_info(int received, struct in_addr dst, int msecs, int usecs, struct sockaddr_ll from){printf("%03d ", received);printf("%s ", from.sll_pkttype==PACKET_HOST ? "Unicast" : "Broadcast");printf("%s from %s", "reply", inet_ntoa(dst) );printf(" [%02X:%02X:%02X:%02X:%02X:%02X] ", from.sll_addr[0], from.sll_addr[1], \ from.sll_addr[2], from.sll_addr[3], from.sll_addr[4], from.sll_addr[5]); printf(" %ld.%ld ms\n", (long int)msecs, (long int)usecs);fflush(stdout);}void finish(){printf("\nSent %d ARP probe packet(s) \n", send_count);printf("Received %d response(s)", recv_count);printf("\n\n");fflush(stdout);exit(!recv_count);}////////////////////////////////////////////////////////////////intmain(int argc, char **argv){uid_t uid = getuid();setuid(uid);if( *(argv+1) != NULL ) target = *(argv+1);if (inet_aton(target, &dst) != 1) { struct hostent *hp; hp = gethostbyname2(target, AF_INET); printf("\ntarget = %s \n", target ); if (!hp) { fprintf(stderr, "arping: unknown host %s\n", target); exit(2); } memcpy(&dst, hp->h_addr, 4);}src = get_src_ip(device);if (!src.s_addr ) { fprintf(stderr, "arping: no source address in not-DAD mode\n"); exit(2);}socket_id = socket_init();printf("\nARPING %s ", inet_ntoa(dst));printf("from %s %s\n\n", inet_ntoa(src), device ? : "");signal(SIGINT, finish);signal(SIGALRM, send_pkt);send_pkt();while(1){ struct sockaddr_ll from; int alen = sizeof(from); char recv_buf[0x1000]; int recv_size = recvfrom(socket_id, recv_buf, sizeof(recv_buf), 0, (struct sockaddr *)&from, &alen ); gettimeofday(&recv_time, NULL); if( recv_size < 0 ) { perror("arping: recvfrom"); continue; } if( chk_recv_pkt(recv_buf, &from) > 0 ) { memcpy(he.sll_addr, from.sll_addr, he.sll_halen); long usecs, msecs; if (recv_time.tv_sec) { usecs = (recv_time.tv_sec - send_time.tv_sec) * 1000000 + recv_time.tv_usec - send_time.tv_usec; msecs = (usecs+500)/1000; usecs -= msecs*1000 - 500; } recv_count++; disp_info(recv_count, dst, msecs, usecs, from); } // if (chk...) }return 0;}
免费ARP简单介绍和程序编写
免费ARP,在网络上有很多的介绍。在《tcp/ip协议卷》中的第四章也有介绍,下面再啰嗦一下介绍其作用和操作:
免费ARP,主要用于检测网络中IP地址是否冲突,它是一种功能而非协议。当设备重启或代理ARP功能开启时就会向本地网络主动发免费ARP以检测IP地址是否冲突。免费ARP是以源、目的IP都是自己,源MAC也是自己,目标MAC是广播,即向自己所在网络请求自己的MAC地址,当网络中如果有其他主机使用了与自己相同的IP地址,他就会给主机一个ARP回复,此时如果发免费ARP的主机收到了回复就证明自己所用的IP地址有冲突,如果没有收到回复则说明没有IP地址冲突。
(若上面的文字有雷同,则以别人的文章为主;若有版权请告知我,本人会在24小时撤掉,谢谢~~~)
下面是免费ARP的代码,作为一个参考吧:
- /////////////////////////////////////////////////////////////////////////////////
- // 文件名: arp_func.c
- // 作者: cfjtaishan
- // 版本: 1.0
- // 日期: 2013-05-14
- // 描述: 免费ARP--用于检测IP地址是否冲突.
- // 历史记录:
- /////////////////////////////////////////////////////////////////////////////////
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <linux/if_packet.h>
- #include <netdb.h>
- #include <unistd.h>
- #include <arpa/inet.h>
- #include <sys/ioctl.h>
- #include <net/ethernet.h>
- #include <netinet/ether.h>
- #include <net/if.h>
- #include <netinet/ip.h>
- #define FAILURE -1
- #define SUCCESS 0
- unsigned char src_ip[4] = { 192, 168, 9, 118 }; //要检测的主机IP地址
- unsigned char src_mac[6] = {0x00, 0x0c, 0x29, 0x4b, 0x6c, 0x13}; //要检测的主机的MAC地址
- unsigned char dst_ip[4] = { 192, 168, 9, 118 }; //目标IP地址
- unsigned char dst_mac[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; //ARP广播地址
- int send_arp(int sockfd, struct sockaddr_ll *peer_addr);
- int recv_arp(int sockfd, struct sockaddr_ll *peer_addr);
- //ARP封装包
- typedef struct _tagARP_PACKET{
- struct ether_header eh;
- struct ether_arp arp;
- }ARP_PACKET_OBJ, *ARP_PACKET_HANDLE;
- int main(int argc, char *argv[])
- {
- int sockfd;
- int rtval = -1;
- struct sockaddr_ll peer_addr;
- //创建socket
- sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
- if (sockfd < 0)
- {
- fprintf(stderr, "socket error: %s\n", strerror(errno));
- exit(EXIT_FAILURE);
- }
- memset(&peer_addr, 0, sizeof(peer_addr));
- peer_addr.sll_family = AF_PACKET;
- struct ifreq req;
- bzero(&req, sizeof(struct ifreq));
- strcpy(req.ifr_name, "eth0");
- if(ioctl(sockfd, SIOCGIFINDEX, &req) != 0)
- perror("ioctl()");
- peer_addr.sll_ifindex = req.ifr_ifindex;
- peer_addr.sll_protocol = htons(ETH_P_ARP);
- //peer_addr.sll_family = AF_PACKET;
- while (1)
- {
- rtval = send_arp(sockfd, &peer_addr);
- if (FAILURE == rtval)
- {
- fprintf(stderr, "Send arp socket failed: %s\n", strerror(errno));
- }
- rtval = recv_arp(sockfd, &peer_addr);
- if (rtval == SUCCESS)
- {
- printf ("Get packet from peer and IP conflicts!\n");
- }
- else if (rtval == FAILURE)
- {
- fprintf(stderr, "Recv arp IP not conflicts: %s\n", strerror(errno));
- }
- else
- {
- fprintf(stderr, "Recv arp socket failed: %s\n", strerror(errno));
- }
- //sleep(1);
- }
- return 0;
- }
- //////////////////////////////////////////////////////////////////////////
- // 函数名: send_arp
- // 描述 : 填充ARP数据包报文并发送出去。
- // 参数:
- // [in] sockfd -- 创建的socket描述符;
- // [in] peer_addr -- 对端的IP信息
- // 返回值:
- // 成功: SUCCESS, 失败: FAILURE;
- // 说明:
- //////////////////////////////////////////////////////////////////////////
- int send_arp(int sockfd, struct sockaddr_ll *peer_addr)
- {
- int rtval;
- ARP_PACKET_OBJ frame;
- memset(&frame, 0x00, sizeof(ARP_PACKET_OBJ));
- //填充以太网头部
- memcpy(frame.eh.ether_dhost, dst_mac, 6); //目的MAC地址
- memcpy(frame.eh.ether_shost, src_mac, 6); //源MAC地址
- frame.eh.ether_type = htons(ETH_P_ARP); //协议
- //填充ARP报文头部
- frame.arp.ea_hdr.ar_hrd = htons(ARPHRD_ETHER); //硬件类型
- frame.arp.ea_hdr.ar_pro = htons(ETHERTYPE_IP); //协议类型 ETHERTYPE_IP | ETH_P_IP
- frame.arp.ea_hdr.ar_hln = 6; //硬件地址长度
- frame.arp.ea_hdr.ar_pln = 4; //协议地址长度
- frame.arp.ea_hdr.ar_op = htons(ARPOP_REQUEST); //ARP请求操作
- memcpy(frame.arp.arp_sha, src_mac, 6); //源MAC地址
- memcpy(frame.arp.arp_spa, src_ip, 4); //源IP地址
- memcpy(frame.arp.arp_tha, dst_mac, 6); //目的MAC地址
- memcpy(frame.arp.arp_tpa, dst_ip, 4); //目的IP地址
- rtval = sendto(sockfd, &frame, sizeof(ARP_PACKET_OBJ), 0,
- (struct sockaddr*)peer_addr, sizeof(struct sockaddr_ll));
- if (rtval < 0)
- {
- return FAILURE;
- }
- return SUCCESS;
- }
- //////////////////////////////////////////////////////////////////////////
- // 函数名: recv_arp
- // 描述 : 接收ARP回复数据报文并判断是不是对免费ARP的回复。
- // 参数:
- // [in] sockfd -- 创建的socket描述符;
- // [in] peer_addr -- 对端的IP信息
- // 返回值:
- // 成功: SUCCESS, 失败: FAILURE;
- // 说明:
- // 若是对免费arp请求的回复则返回:SUCCESS.
- //////////////////////////////////////////////////////////////////////////
- int recv_arp(int sockfd, struct sockaddr_ll *peer_addr)
- {
- int rtval;
- ARP_PACKET_OBJ frame;
- memset(&frame, 0, sizeof(ARP_PACKET_OBJ));
- rtval = recvfrom(sockfd, &frame, sizeof(frame), 0,
- NULL, NULL);
- //判断是否接收到数据并且是否为回应包
- if (htons(ARPOP_REPLY) == frame.arp.ea_hdr.ar_op && rtval > 0)
- {
- //判断源地址是否为冲突的IP地址
- if (memcmp(frame.arp.arp_spa, src_ip, 4) == 0)
- {
- fprintf(stdout, "IP address is common~\n");
- return SUCCESS;
- }
- }
- if (rtval < 0)
- {
- return FAILURE;
- }
- return FAILURE;
- }
该程序可以测试局域网中的某个IP地址是否有冲突的,以便于确定该地址是否可以作为本机的IP地址。下面是通过wireshark抓到了免费的ARP数据包,以及回应包,如下:
0 0
- ARP的C代码实现
- ARP C代码实现
- ARP--C语言Windows实现
- 使用ioctl()函数获取ARP高速缓存例子的c实现
- ARP协议的实现
- ARP协议的实现
- ARP攻击测试代码(C)
- 用JAVA代码实现ARP攻击
- 用JAVA代码实现ARP攻击
- ARP协议(ARP脚本抓取主机MAC的实现)
- arp.c
- 基于ARP的局域网IP劫持——C语言实现
- 堆栈的C代码实现
- 栈的c代码实现
- 队列的c代码实现
- linux下的arp欺骗实现
- ARP 地址解析的实现过程
- linux下arp攻击的实现
- 使用CL.EXE查看C++中类的内存结构
- 阿里前端的困局与突围
- eclipse导入openfire源码
- MIPI vedio mode introduce
- 网络基础(3)- 网络层:IP地址、子网掩码和路由器的作用
- ARP的C代码实现
- 那些不能错过的Xcode插件
- __I、 __O 、__IO volatile是什么?怎么用?
- 关于window.location.href无法跳转的解决办法
- spi_sync()说明
- 安装YCM
- VS2010数据库(SQL SERVER 2008)连接与操作(1)
- 光耦相关1
- SVN版本比较时旧版本的中文乱码问题