我是靠谱客的博主 老实秋天,最近开发中收集的这篇文章主要介绍原始套接字--icmp相关,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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!!!n");
close(sockfd);
}
int main(int argc, const char *argv[])
{
if (argc != 2)
{
printf("usage:%s dst_ipn", 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("===============================n");
printf("from ip:%sn", inet_ntoa(ip_header->ip_src));
printf("icmp_type:%dn", icmp_packet->icmp_type);
printf("icmp_code:%dn", icmp_packet->icmp_code);
printf("time interval:%.3fmsn", 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( "n" );
}
}
printf( "n" );
return 0;
}
static int
xdump_frame_ether(struct ether_header *eth)
{
if (NULL == eth) {
return -1;
}
printf("========frame ether========n");
printf("type :0x%04xn", htons(eth->ether_type));
printf("d-mac:%02x-%02x-%02x-%02x-%02x-%02xn",
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-%02xn",
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
========n");
printf("arp_hrd=%d
n", htons(arp->arp_hrd));
printf("arp_pro=0x%04xn", htons(arp->arp_pro));
printf("arp_op =%d
n", htons(arp->arp_op));
printf("arp_sdr=%02x-%02x-%02x-%02x-%02x-%02x %d.%d.%d.%dn", 
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.%dn", 
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
========n");
printf("ip_v
=0x%xn", iph->ip_v
); /* 4位版本号
*/
printf("ip_hl =0x%xn", iph->ip_hl
); /* 4位IP头部长度 32bit */
printf("ip_tos=0x%xn", iph->ip_tos
); /* 8位服务类型
*/
printf("ip_len=0x%xn", htons(iph->ip_len)
); /*16位数据包总长度
*/
printf("ip_id =0x%xn", htons(iph->ip_id)
); /*16位标志符
*/
printf("ip_off=0x%xn", htons(iph->ip_off)
); /* 3位标记+13位片偏移
*/
printf("ip_ttl=0x%xn", iph->ip_ttl
); /* 8位生存时间
*/
printf("ip_p
=0x%xn", iph->ip_p
); /* 8位协议号
*/
printf("ip_sum=0x%xn", htons(iph->ip_sum)
); /*16位首部校验和
*/
printf("ip_src=%s
n", inet_ntoa(iph->ip_src)); /*32位源地址
*/
printf("ip_dst=%s
n", inet_ntoa(iph->ip_dst)); /*32位目的地址
*/
return 0;
}
static int
xdump_frame_icmp (struct icmp *icmph)
{
if (NULL == icmph) {
return -1;
}
printf("========frame icmp ========n");
printf("icmp_type =0x%xn", icmph->icmp_type ); /*
8位类型
*/
printf("icmp_code =0x%xn", icmph->icmp_code ); /*
8位代码
*/
printf("icmp_cksum=0x%xn", icmph->icmp_cksum); /* 16位校验和
*/
printf("icmp_id
=0x%xn", icmph->icmp_id
); /* 16位识别号 进程id */
printf("icmp_seq
=0x%xn", 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)n", 
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=%dn", 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)n", 
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("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++n");
printf("========frame size:%dn", s_frame_size);
xdump_frame_ether(eth);
xdump_frame_arp
(arp);
printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++n");
printf("n");
#endif
if (s_frame_size != xsend_frame_ether(
s_frame_data, s_frame_size, s_interface_index, skfd)) {
return -1;
}
xprint_log("ok. size=%dn", 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("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++n");
printf("========frame size:%dn", s_frame_size);
xdump_frame_ether(eth
);
xdump_frame_ip
(iph
);
xdump_frame_icmp (icmph);
printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++n");
printf("n");
#endif
if (s_frame_size != xsend_frame_ether( 
s_frame_data, s_frame_size, s_interface_index, skfd)) {
return -1;
}
xprint_log("ok. size=%dn", 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 ipaddrn",argv[0]);
printf("
ex: %s eth0 192.168.88.1n", argv[0]);
return -1;
}
skfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (skfd < 0) {
xprint_err("socket() failed! errno=%d (%s)n", 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)n", 
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)n", 
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)n", 
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)n", 
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)n", 
errno, strerror(errno));
return -1;
}
}
printf("========host info
========n");
printf("ifr_ifindex=%d %sn", s_interface_index, argv[1]);
printf("ifr_hwaddr =%02x-%02x-%02x-%02x-%02x-%02xn", 
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
=%sn", inet_ntoa(s_interface_ip));
printf("ifr_flags
=IFF_PROMISCn");
printf("pid
=0x%xn", getpid());
printf("header_eth =%dn", HDR_LEN_ETH);
printf("header_arp =%dn", HDR_LEN_ARP);
printf("header_ip
=%dn", HDR_LEN_IP);
printf("header_icmp=%dn", HDR_LEN_ICMP);
printf("n");
printf("press any key continue!n");
getchar();
printf("waiting for someone ping %s ...n", 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)n", 
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;
}

 

转载于:https://www.cnblogs.com/tla001/p/6592418.html

最后

以上就是老实秋天为你收集整理的原始套接字--icmp相关的全部内容,希望文章能够帮你解决原始套接字--icmp相关所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部