icmp请求
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <netinet/ip_icmp.h> #include <sys/time.h> /* icmp报文长度 */ #define ICMP_PACKET_LEN sizeof(struct icmp) void err_exit(const char *err_msg) { perror(err_msg); exit(1); } /* 校验和 */ unsigned short check_sum(unsigned short *addr, int len) { int nleft = len; int sum = 0; unsigned short *w = addr; unsigned short answer = 0; while(nleft > 1) { sum += *w++; nleft -= 2; } if(nleft == 1) { *(unsigned char *)(&answer) = *(unsigned char *)w; sum += answer; } sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); answer = ~sum; return answer; } /* 填充icmp报文 */ struct icmp *fill_icmp_packet(int icmp_type, int icmp_sequ) { struct icmp *icmp_packet; icmp_packet = (struct icmp *)malloc(ICMP_PACKET_LEN); icmp_packet->icmp_type = icmp_type; icmp_packet->icmp_code = 0; icmp_packet->icmp_cksum = 0; icmp_packet->icmp_id = htons(getpid()); icmp_packet->icmp_seq = htons(icmp_sequ); /* 发送时间 */ gettimeofday((struct timeval *)icmp_packet->icmp_data, NULL); /* 校验和 */ icmp_packet->icmp_cksum = check_sum((unsigned short *)icmp_packet, ICMP_PACKET_LEN); return icmp_packet; } /* 发送icmp请求 */ void icmp_request(const char *dst_ip, int icmp_type, int icmp_sequ) { struct sockaddr_in dst_addr; struct icmp *icmp_packet; int sockfd, ret_len; char buf[ICMP_PACKET_LEN]; /* 请求的地址 */ bzero(&dst_addr, sizeof(struct sockaddr_in)); dst_addr.sin_family = AF_INET; dst_addr.sin_addr.s_addr = inet_addr(dst_ip); if ((sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1) err_exit("sockfd()"); /* icmp包 */ icmp_packet = fill_icmp_packet(icmp_type, icmp_sequ); memcpy(buf, icmp_packet, ICMP_PACKET_LEN); /* 发送请求 */ ret_len = sendto(sockfd, buf, ICMP_PACKET_LEN, 0, (struct sockaddr *)&dst_addr, sizeof(struct sockaddr_in)); if (ret_len > 0) printf("sendto() ok!!! "); close(sockfd); } int main(int argc, const char *argv[]) { if (argc != 2) { printf("usage:%s dst_ip ", argv[0]); exit(1); } /* 发送icmp请求 */ icmp_request(argv[1], 8, 1); return 0; }
icmp接收
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/time.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_icmp.h> /* IP首部长度 */ #define IP_HEADER_LEN sizeof(struct ip) /* icmp报文长度 */ #define ICMP_PACKET_LEN sizeof(struct icmp) /* IP + ICMP长度 */ #define IP_ICMP_PACKET_LEN IP_HEADER_LEN + ICMP_PACKET_LEN void err_exit(const char *err_msg) { perror(err_msg); exit(1); } /* 计算发送时间与接收时间的毫秒差 */ float time_interval(struct timeval *recv_time, struct timeval *send_time) { float msec = 0; /* 如果接收的时间微妙小于发送的微妙 */ if (recv_time->tv_usec < send_time->tv_usec) { recv_time->tv_sec -= 1; recv_time->tv_usec += 1000000; } msec = (recv_time->tv_sec - send_time->tv_sec) * 1000.0 + (recv_time->tv_usec - send_time->tv_usec) / 1000.0; return msec; } int main(void) { struct ip *ip_header; struct icmp *icmp_packet; char buf[IP_ICMP_PACKET_LEN]; struct timeval *recv_timeval, *send_timeval; int sockfd, ret_len; if ((sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1) err_exit("sockfd()"); recv_timeval = malloc(sizeof(struct timeval)); while (1) { ret_len = recv(sockfd, buf, IP_ICMP_PACKET_LEN, 0); if (ret_len > 0) { /* 接收时间 */ gettimeofday(recv_timeval, NULL); /* 取出ip首部 */ /* 取出icmp报文 */ ip_header = (struct ip *)buf; icmp_packet = (struct icmp *)(buf + IP_HEADER_LEN); /* 取出发送时间 */ send_timeval = (struct timeval *)icmp_packet->icmp_data; printf("=============================== "); printf("from ip:%s ", inet_ntoa(ip_header->ip_src)); printf("icmp_type:%d ", icmp_packet->icmp_type); printf("icmp_code:%d ", icmp_packet->icmp_code); printf("time interval:%.3fms ", time_interval(recv_timeval, send_timeval)); } } free(recv_timeval); close(sockfd); return 0; }
arp-icmp应答伪装
#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 <net/ethernet.h> #include <net/if_arp.h> #include <net/if.h> #include <netinet/if_ether.h> #include <netinet/ip_icmp.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netpacket/packet.h> #include <arpa/inet.h> #ifndef arp_hrd /*android not define struct ether_arp*/ struct ether_arp { struct arphdr ea_hdr; /* fixed-size 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 #endif #define xprint_log(fmt, ...) printf("[%04d]%s() " fmt, __LINE__, __FUNCTION__, ####__VA_ARGS__) #define xprint_err(fmt, ...) printf("[%04d]%s() err: " fmt, __LINE__, __FUNCTION__, ####__VA_ARGS__) #define xdebug 0 #define xunused __attribute__((unused)) #define HDR_LEN_ETH sizeof(struct ether_header) #define HDR_LEN_ARP sizeof(struct ether_arp) #define HDR_LEN_IP sizeof(struct ip) #define HDR_LEN_ICMP sizeof(struct icmp) static unsigned char s_frame_data[ETH_FRAME_LEN]; static unsigned int s_frame_size = 0; static int s_interface_index = -1; static unsigned char s_interface_mac[ETH_ALEN]; static struct in_addr s_interface_ip; static unsigned char s_src_mac[ETH_ALEN] = {0x38,0x97,0xd6,0x51,0xa0,0x02}; static int xsend_frame_ether(uint8_t *frame, int size, int ifindex, int skfd); static int xrecv_frame_ether(uint8_t *frame, int size, int ifindex, int skfd); static int xsend_reply_arp(in_addr_t ipaddr, int skfd); static int xsend_reply_icmp(in_addr_t ipaddr, int skfd); static uint16_t xutil_check_sum(uint16_t* data, int size); static void xutil_swap_int(uint32_t *a, uint32_t *b); static int xunused xdump_frame_byte(uint8_t *data, int size); static int xunused xdump_frame_ether(struct ether_header *eth); static int xunused xdump_frame_arp (struct ether_arp *arp); static int xunused xdump_frame_ip (struct ip *iph); static int xunused xdump_frame_icmp (struct icmp *icmph); #define __DEFINITION__ static uint16_t xutil_check_sum(uint16_t* data, int size) { unsigned int cksm = 0; while (size > 1) { cksm += *data++; size -= sizeof(uint16_t); } if (size) { cksm += *(uint8_t*)data; } cksm = (cksm>>16) + (cksm&0xffff); cksm += (cksm>>16); return (uint16_t)(~cksm); } static void xutil_swap_int(uint32_t *a, uint32_t *b) { *a = *a ^ *b; *b = *a ^ *b; *a = *a ^ *b; return ; } static int xdump_frame_byte(uint8_t *data, int size) { int i; for(i=0; i<size; i++) { if((i%16) == 0) { printf( "[%02x] ", i/16 ); } printf( "%02x ", data[i] ); if(((i+1)%16) == 0) { printf( " " ); } } printf( " " ); return 0; } static int xdump_frame_ether(struct ether_header *eth) { if (NULL == eth) { return -1; } printf("========frame ether======== "); printf("type :0x%04x ", htons(eth->ether_type)); printf("d-mac:%02x-%02x-%02x-%02x-%02x-%02x ", eth->ether_dhost[0], eth->ether_dhost[1], eth->ether_dhost[2], eth->ether_dhost[3], eth->ether_dhost[4], eth->ether_dhost[5]); printf("s-mac:%02x-%02x-%02x-%02x-%02x-%02x ", eth->ether_shost[0], eth->ether_shost[1], eth->ether_shost[2], eth->ether_shost[3], eth->ether_shost[4], eth->ether_shost[5]); return 0; } static int xdump_frame_arp (struct ether_arp *arp) { if (NULL == arp) { return -1; } printf("========frame arp ======== "); printf("arp_hrd=%d ", htons(arp->arp_hrd)); printf("arp_pro=0x%04x ", htons(arp->arp_pro)); printf("arp_op =%d ", htons(arp->arp_op)); printf("arp_sdr=%02x-%02x-%02x-%02x-%02x-%02x %d.%d.%d.%d ", arp->arp_sha[0], arp->arp_sha[1], arp->arp_sha[2], arp->arp_sha[3], arp->arp_sha[4], arp->arp_sha[5], arp->arp_spa[0], arp->arp_spa[1], arp->arp_spa[2], arp->arp_spa[3]); printf("arp_tgr=%02x-%02x-%02x-%02x-%02x-%02x %d.%d.%d.%d ", arp->arp_tha[0], arp->arp_tha[1], arp->arp_tha[2], arp->arp_tha[3], arp->arp_tha[4], arp->arp_tha[5], arp->arp_tpa[0], arp->arp_tpa[1], arp->arp_tpa[2], arp->arp_tpa[3]); return 0; } static int xdump_frame_ip(struct ip *iph) { if (NULL == iph) { return -1; } printf("========frame ip ======== "); printf("ip_v =0x%x ", iph->ip_v ); /* 4位版本号 */ printf("ip_hl =0x%x ", iph->ip_hl ); /* 4位IP头部长度 32bit */ printf("ip_tos=0x%x ", iph->ip_tos ); /* 8位服务类型 */ printf("ip_len=0x%x ", htons(iph->ip_len) ); /*16位数据包总长度 */ printf("ip_id =0x%x ", htons(iph->ip_id) ); /*16位标志符 */ printf("ip_off=0x%x ", htons(iph->ip_off) ); /* 3位标记+13位片偏移 */ printf("ip_ttl=0x%x ", iph->ip_ttl ); /* 8位生存时间 */ printf("ip_p =0x%x ", iph->ip_p ); /* 8位协议号 */ printf("ip_sum=0x%x ", htons(iph->ip_sum) ); /*16位首部校验和 */ printf("ip_src=%s ", inet_ntoa(iph->ip_src)); /*32位源地址 */ printf("ip_dst=%s ", inet_ntoa(iph->ip_dst)); /*32位目的地址 */ return 0; } static int xdump_frame_icmp (struct icmp *icmph) { if (NULL == icmph) { return -1; } printf("========frame icmp ======== "); printf("icmp_type =0x%x ", icmph->icmp_type ); /* 8位类型 */ printf("icmp_code =0x%x ", icmph->icmp_code ); /* 8位代码 */ printf("icmp_cksum=0x%x ", icmph->icmp_cksum); /* 16位校验和 */ printf("icmp_id =0x%x ", icmph->icmp_id ); /* 16位识别号 进程id */ printf("icmp_seq =0x%x ", icmph->icmp_seq ); /* 16位序列号 */ return 0; } static int xsend_frame_ether(uint8_t *frame, int size, int ifindex, int skfd) { struct sockaddr_ll sll; socklen_t sln = 0; struct sockaddr_ll *psll = NULL; if (-1 != ifindex) { bzero(&sll, sizeof(sll)); sll.sll_ifindex = ifindex; sll.sll_family = PF_PACKET; sll.sll_protocol = htons(ETH_P_ALL); psll = &sll; sln = sizeof(struct sockaddr_ll); } size = sendto(skfd, frame, size, 0, (struct sockaddr*)psll, sln); if (size < 0) { xprint_err("ioctl() SIOCGIFINDEX failed! errno=%d (%s) ", errno, strerror(errno)); } return size; } static int xrecv_frame_ether(uint8_t *frame, int size, int ifindex, int skfd) { struct sockaddr_ll sll; socklen_t sln = sizeof(struct sockaddr_ll); struct sockaddr_ll *psll = NULL; socklen_t *psln = NULL; if (NULL==frame || size<=0) { xprint_err("param failed! frame=%p size=%d ", frame, size); return -1; } if (-1 != ifindex) { bzero(&sll, sizeof(sll)); sll.sll_ifindex = ifindex; sll.sll_family = PF_PACKET; sll.sll_protocol = htons(ETH_P_ALL); psll = &sll; psln = &sln; } memset(frame, 0, size*sizeof(uint8_t)); size = recvfrom(skfd, frame, size, 0, (struct sockaddr*)psll, psln); if (size < 0) { xprint_err("recvfrom() failed! errno=%d (%s) ", errno, strerror(errno)); } return size; } static int xsend_reply_arp(in_addr_t ipaddr, int skfd) { struct ether_header *eth = NULL; struct ether_arp *arp = NULL; eth = (struct ether_header*)s_frame_data; arp = (struct ether_arp*)(s_frame_data + HDR_LEN_ETH); if (*(unsigned int*)arp->arp_tpa != ipaddr) { return -1; } /*ether*/ memcpy(eth->ether_dhost, eth->ether_shost, ETH_ALEN); memcpy(eth->ether_shost, s_src_mac , ETH_ALEN); /*arp*/ arp->arp_op = htons(ARPOP_REPLY); memcpy(arp->arp_tha, arp->arp_sha, ETH_ALEN); memcpy(arp->arp_tpa, arp->arp_spa, 4); memcpy(arp->arp_sha, s_src_mac, ETH_ALEN); memcpy(arp->arp_spa, &ipaddr, 4); #if xdebug printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ "); printf("========frame size:%d ", s_frame_size); xdump_frame_ether(eth); xdump_frame_arp (arp); printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ "); printf(" "); #endif if (s_frame_size != xsend_frame_ether( s_frame_data, s_frame_size, s_interface_index, skfd)) { return -1; } xprint_log("ok. size=%d ", s_frame_size); return 0; } static int xsend_reply_icmp(in_addr_t ipaddr, int skfd) { struct ip *iph = NULL; struct ether_header *eth = NULL; struct icmp *icmph = NULL; eth = (struct ether_header*)s_frame_data; iph = (struct ip*)(s_frame_data + HDR_LEN_ETH); icmph = (struct icmp*)(s_frame_data + HDR_LEN_ETH + HDR_LEN_IP); if ((iph->ip_p!=IPPROTO_ICMP) || iph->ip_dst.s_addr!=ipaddr) { return 1; } /*ether*/ memcpy(eth->ether_dhost, eth->ether_shost, ETH_ALEN); memcpy(eth->ether_shost, s_src_mac, ETH_ALEN); /*ip*/ xutil_swap_int(&(iph->ip_src.s_addr), &(iph->ip_dst.s_addr)); iph->ip_off = 0; iph->ip_sum = 0; iph->ip_sum = xutil_check_sum((uint16_t*)iph, HDR_LEN_IP); /*icmp*/ icmph->icmp_type = ICMP_ECHOREPLY; icmph->icmp_cksum = 0; icmph->icmp_cksum = xutil_check_sum((uint16_t*)icmph, s_frame_size-HDR_LEN_ETH-HDR_LEN_IP); #if xdebug printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ "); printf("========frame size:%d ", s_frame_size); xdump_frame_ether(eth ); xdump_frame_ip (iph ); xdump_frame_icmp (icmph); printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ "); printf(" "); #endif if (s_frame_size != xsend_frame_ether( s_frame_data, s_frame_size, s_interface_index, skfd)) { return -1; } xprint_log("ok. size=%d ", s_frame_size); return 0; } int main(int argc, char **argv) { int skfd = -1; in_addr_t xping_addr = 0; if (argc <= 2) { printf("usage: %s interface ipaddr ",argv[0]); printf(" ex: %s eth0 192.168.88.1 ", argv[0]); return -1; } skfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (skfd < 0) { xprint_err("socket() failed! errno=%d (%s) ", errno, strerror(errno)); return -1; } struct ifreq ifr; bzero(&ifr,sizeof(ifr)); strcpy(ifr.ifr_name, argv[1]); if (-1 == ioctl(skfd, SIOCGIFINDEX, &ifr)) { xprint_err("ioctl() SIOCGIFINDEX failed! errno=%d (%s) ", errno, strerror(errno)); return -1; } s_interface_index = ifr.ifr_ifindex; if (-1 == ioctl(skfd, SIOCGIFHWADDR, &ifr)) { xprint_err("ioctl() SIOCGIFHWADDR failed! errno=%d (%s) ", errno, strerror(errno)); return -1; } memcpy(s_interface_mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN); if (-1 == ioctl(skfd, SIOCGIFADDR, &ifr)) { xprint_err("ioctl() SIOCGIFADDR failed! errno=%d (%s) ", errno, strerror(errno)); return -1; } s_interface_ip.s_addr = ((struct sockaddr_in*)&(ifr.ifr_addr))->sin_addr.s_addr; if (-1 == ioctl(skfd, SIOCGIFFLAGS, &ifr)) { xprint_err("ioctl() IFF_PROMISC failed! errno=%d (%s) ", errno, strerror(errno)); return -1; } if ((ifr.ifr_flags&IFF_PROMISC) != IFF_PROMISC) { ifr.ifr_flags |= IFF_PROMISC; if(-1 == ioctl(skfd, SIOCSIFFLAGS, &ifr)) { xprint_err("ioctl() IFF_PROMISC failed! errno=%d (%s) ", errno, strerror(errno)); return -1; } } printf("========host info ======== "); printf("ifr_ifindex=%d %s ", s_interface_index, argv[1]); printf("ifr_hwaddr =%02x-%02x-%02x-%02x-%02x-%02x ", s_interface_mac[0], s_interface_mac[1], s_interface_mac[2], s_interface_mac[3], s_interface_mac[4], s_interface_mac[5]); printf("ifr_addr =%s ", inet_ntoa(s_interface_ip)); printf("ifr_flags =IFF_PROMISC "); printf("pid =0x%x ", getpid()); printf("header_eth =%d ", HDR_LEN_ETH); printf("header_arp =%d ", HDR_LEN_ARP); printf("header_ip =%d ", HDR_LEN_IP); printf("header_icmp=%d ", HDR_LEN_ICMP); printf(" "); printf("press any key continue! "); getchar(); printf("waiting for someone ping %s ... ", argv[2]); #if 0 int on = 1; if (0 != setsockopt(skfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on))) { xprint_err("setsockopt() IP_HDRINCL failed! errno=%d (%s) ", errno, strerror(errno)); return -1; } #endif xping_addr = inet_addr(argv[2]); while(1) { uint16_t ether_type = 0; struct ether_header* eth = NULL; memset(s_frame_data, 0x00, sizeof(unsigned char)*ETH_FRAME_LEN); s_frame_size = xrecv_frame_ether(s_frame_data, ETH_FRAME_LEN, s_interface_index, skfd); eth = (struct ether_header*)s_frame_data; ether_type = htons(eth->ether_type); switch(ether_type) { case ETHERTYPE_ARP: { xsend_reply_arp(xping_addr, skfd); break; } case ETHERTYPE_IP: { xsend_reply_icmp(xping_addr, skfd); break; } default: { break; } } } close(skfd); return 0; }