📄 arpd.c
字号:
/* * File: arpd.c * * Author: zhubo@legendsec.com * * Date: 2008-08-18 * * Brief: arpd deamon that query the arp information * */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <signal.h>#include <errno.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/types.h>#include <sys/stat.h>#include <linux/sockios.h>#include <net/if.h>#include <net/if_arp.h>#include <arpa/inet.h>#include <netinet/in.h>#include <netinet/if_ether.h>#define BUFSIZE 186#define MAX_ROW 10#define GATEWAY_ROW 1#define GATEWAY_NUM 10#define SIOCGARPMSG 0x1003typedef struct _ether_pkg_ { unsigned char ether_dhost[6]; unsigned char ether_shost[6]; unsigned short int ether_type; unsigned short int ar_hrd; unsigned short int ar_pro; unsigned char ar_hln; unsigned char ar_pln; unsigned short int ar_op; unsigned char arp_sha[6]; unsigned char arp_spa[4]; unsigned char arp_tha[6]; unsigned char arp_tpa[4]; }ether_pkg; unsigned int gateway_num = 0;unsigned int time_lag = 0;char *device = {0};static void usage(){ printf("\nUsage: arpd\n" " -t <time> the time interval to detect IP conflict\n" " -d <interface> specify the net interface name\n" " -h help\n"); exit(-1);}static void parse_args(int argc, char *argv[]){ int ch = 0; while ((ch = getopt(argc, argv, "t:d:h")) != -1) { switch(ch) { case 't': time_lag = atoi(optarg); break; case 'd': device = optarg; break; case 'h': default: usage(argv[0]); break; } } if (argc <= 1) usage(); if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); exit (-1); }}/* initialize the deamon */static void deamon_init(void){ pid_t pid; umask(0); pid = fork(); if (pid) exit(0); else if (pid < 0) exit(1); if (chdir("/") < 0) { perror("chdir()"); exit(1); } setsid(); pid = fork(); if (pid) exit(0); else if (pid < 0) exit(1); signal(SIGCHLD, SIG_IGN);}/* get the IP address of the gateway by reading the route table /proc/net/route */static int get_gateway(struct sockaddr_in *gateway_addr){ if (gateway_addr == NULL) return -1; FILE *fp = NULL; unsigned char buf[BUFSIZE] = {0}; unsigned long route[MAX_ROW] = {0}; unsigned char *ip = NULL; char iface[8] = {0}; int lines = 0; int nitems = 0; int num = 0; struct in_addr gate_addr; buf[BUFSIZE-1] = 0; fp = fopen("/proc/net/route", "rb"); if (!fp) { fprintf(stderr, "Unable to open route table\n"); return -1; } lines = 0; while (1) { if (!fgets(buf, BUFSIZE-1, fp)) { fclose(fp); break; } lines++; nitems = sscanf(buf, "%s %lx %lx", iface, route, route+1); if (nitems == 3 && lines > 1) { if (route[GATEWAY_ROW]) { gate_addr.s_addr = route[GATEWAY_ROW]; (gateway_addr + num)->sin_addr = gate_addr; num++; ip = inet_ntoa(gate_addr); fprintf(stderr, "The gateway IP on interface %s is:%s\n", iface, ip); } continue; } } gateway_num = num; fprintf(stderr, "There are %d lines in route table and %d gateway\n", lines, gateway_num); return 0;}/* get local mac and ip address*/int get_local_mac_ip(unsigned char *local_mac, unsigned char *local_ip) { if ( NULL == local_mac) { fprintf(stderr, "%s %d:invalid argument", __func__, __LINE__); return -1; } int sockfd; struct ifreq req; struct sockaddr_in *sin; if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { fprintf(stderr, "Sock Error:%s\n\a", strerror(errno)); return -1; } memset(local_mac, 0, sizeof(local_mac)); memset(local_ip, 0, sizeof(local_ip)); memset(&req, 0, sizeof(req)); strcpy(req.ifr_name, device); if(ioctl(sockfd, SIOCGIFHWADDR, (char *)&req) == -1) { fprintf(stderr, "ioctl SIOCGIFHWADDR:%s\n\a", strerror(errno)); close(sockfd); return -1; } memcpy(local_mac, req.ifr_hwaddr.sa_data, 6); req.ifr_addr.sa_family = AF_INET; if(ioctl(sockfd, SIOCGIFADDR, (char *)&req) == -1) { fprintf(stderr, "ioctl SIOCGIFADDR:%s\n\a", strerror(errno)); close(sockfd); return -1; } sin = (struct sockaddr_in *)&req.ifr_addr; memcpy(local_ip, (char *)&(sin->sin_addr), 4); fprintf(stderr, "The local IP is:%s\n", inet_ntoa(sin->sin_addr)); fprintf(stderr, "The local MAC is:%02x:%02x:%02x:%02x:%02x:%02x\n", local_mac[0], local_mac[1], local_mac[2], local_mac[3], local_mac[4], local_mac[5]); return 0; }/* build arp packet and execute arp query */static inline int arp_query(unsigned char *dst_ip, unsigned char *dst_mac){ if ((NULL == dst_ip) || (NULL == dst_mac) || strlen(dst_ip) == 0) return -1; ether_pkg pkg; ether_pkg *parse = NULL; unsigned char buffer[255] = {0}; unsigned char mac[7] = {0}; unsigned char ip[5] ={0}; struct sockaddr_in local_ip; int sockfd = 0; int len = 0; struct sockaddr sa; unsigned char broad_mac[7] = {0xff,0xff,0xff,0xff,0xff,0xff,0x00}; memset(mac, 0, sizeof(mac)); memset(ip, 0, sizeof(ip)); memset(&local_ip, 0, sizeof(struct sockaddr_in)); if(get_local_mac_ip(mac, ip) == -1) return -1; /* build the arp packet */ memset((char *)&pkg, '\0', sizeof(pkg)); memcpy((char *)pkg.ether_shost, (char *)mac, 6); memcpy((char *)pkg.ether_dhost, (char *)broad_mac, 6); pkg.ether_type = htons(ETHERTYPE_ARP); pkg.ar_hrd = htons(ARPHRD_ETHER); pkg.ar_pro = htons(ETHERTYPE_IP); pkg.ar_hln = 6; pkg.ar_pln = 4; pkg.ar_op = htons(ARPOP_REQUEST); memcpy((char *)pkg.arp_sha, (char *)mac, 6); memcpy((char *)pkg.arp_spa, (char *)ip, 4); memcpy((char *)pkg.arp_tha, (char *)broad_mac, 6); memcpy((char *)pkg.arp_tpa, (char *)dst_ip, 4); if((sockfd = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ALL)))==-1) { fprintf(stderr,"Socket Error:%s\n\a", strerror(errno)); return -1; } memset(&sa, 0,sizeof(struct sockaddr)); strcpy(sa.sa_data, device); len = sendto(sockfd, &pkg, sizeof(pkg), 0, &sa, sizeof(sa)); if(len != sizeof(pkg)) { fprintf(stderr,"Sendto Error:%s\n\a", strerror(errno)); return -1; } int i = 0; parse = (ether_pkg *)buffer; while(1) { memset(buffer, 0, sizeof(buffer)); recvfrom(sockfd, buffer, sizeof(buffer), 0, NULL, &len); if((ntohs(parse->ether_type) == ETHERTYPE_ARP) && (ntohs(parse->ar_op) == ARPOP_REPLY)) { memcpy(dst_mac, &parse->arp_tha, 6); fprintf(stderr, "The mac of the host %d.%d.%d.%d is %02x:%02x:%02x:%02x:%02x:%02x\n", dst_ip[0], dst_ip[1], dst_ip[2], dst_ip[3], dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], dst_mac[4],dst_mac[5]); break; } i++; if(i > 255) break; } return 0; }/* communication with the kernel in order to send the arp message to kernel */static inline int send_arp_msg(unsigned char *ip_addr, unsigned char *mac_addr){ if ((NULL == ip_addr) || (NULL == mac_addr) || (strlen (ip_addr) ==0) || (strlen(mac_addr) == 0)) return -1; int fd = 0; char ip[16] = {0}; struct arpreq arpreq; struct sockaddr_in *sin; struct sockaddr *sa; struct in_addr pa; memset(&arpreq, 0, sizeof(struct arpreq)); fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { perror("socket failed\n"); return -1; } sprintf(ip, "%d.%d.%d.%d", ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]); sin = (struct sockaddr_in *)&arpreq.arp_pa; memset(sin, 0, sizeof(struct sockaddr_in)); sin->sin_family = AF_INET; pa.s_addr = inet_addr(ip); memcpy(&sin->sin_addr, &pa, sizeof(struct in_addr)); sa = &arpreq.arp_ha; memset(sa, 0, sizeof(struct sockaddr)); memcpy(sa->sa_data, mac_addr, 6); strcpy(arpreq.arp_dev, device); /* specify the net device name */ arpreq.arp_flags = ATF_COM; if (ioctl(fd, SIOCSARP, &arpreq) == -1) { perror("ioctl failed"); close(fd); return -1; } return 0;}static inline int recieve_arp_msg(char *ip_addr){ if (ip_addr == NULL) return -1; int fd = 0; unsigned int cmd = 0; struct sockaddr_in arp_arg; cmd = SIOCGARPMSG; //the command defined by ourselves fd = socket(AF_INET, SOCK_STREAM, 0); if ( fd < 0 ) { perror( "socket failed" ); return -1; } if ( ioctl(fd, SIOCGARPMSG, &arp_arg) == -1 ) { perror( "ioctl filed" ); close( fd ); return -1; } memcpy(ip_addr, (char *)(&arp_arg.sin_addr), 6); return 0;}static void check_ip(){ unsigned char ip[5] = {0}; unsigned char mac[7] = {0}; unsigned char dst_mac[7] = {0}; if(get_local_mac_ip(mac, ip) == -1) return; if(arp_query(ip, dst_mac) == -1) return; if (strncmp(mac, dst_mac, 6)) fprintf(stderr, "The IP:%s conflict!", ip); alarm(time_lag);}/* the main function */int main(int argc, char *argv[]){ int i = 0; unsigned char ip_addr[5] = {0}; unsigned char mac_addr[7] = {0}; struct sockaddr_in gateway_addr[GATEWAY_NUM]; deamon_init(); parse_args(argc,argv); if(get_gateway(gateway_addr) == -1) { fprintf(stderr, "Can't get gateway address\n"); } if (gateway_num > 0) { for (i = 0; i < gateway_num; i++) { memcpy(ip_addr, (char *)(&gateway_addr[i].sin_addr), 4); arp_query(ip_addr, mac_addr); send_arp_msg(ip_addr, mac_addr); } } signal(SIGALRM, check_ip); alarm(1); while(1) { memset(ip_addr, 0, 4); memset(mac_addr, 0, 6); recieve_arp_msg(ip_addr); arp_query(ip_addr, mac_addr); send_arp_msg(ip_addr, mac_addr); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -