icmp的程序(ping的实现)
code来源于《网络编程与分层协议设计》 chap7 ICMP协议程序设计
----没有理解,没有编译,只是敲了出来
ping.h
#define ICMP_ECHOREPLY 0
#define ICMP_ECHO 8
#define BUFSIZE 1500
#define DEFAULT_LEN 56
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
struct icmphdr{
u8 type;
u8 code;
u16 checksum;
union{
struct {
u16 id;
u16 sequence;
}echo;
u32 gateway;
struct
{
u16 unused;
u16 mtu;
}frag;
}un;
u8 data[0];
#define icmp_id un.echo.id
#define icmp_seq un.echo.sequence
};
#define ICMP_HSIZE sizeof(struct icmphdr)
struct iphdr{
u8 hlen:4, ver:4;
u8 tos;
u16 tot_len;
u16 id;
u16 frag_off;
u8 ttl;
u8 protocol;
u16 check;
u32 saddr;
u32 daddr;
};
char *hostname;
int datalen = DEFAULT_LEN;
char sendbuf[BUFSIZE];
char recvbuf[BUFSIZE];
int nsent;
int nrecv;
pid_t pid;
struct timeval recvtime;
int sockfd;
struct sockaddr_in dest;
struct sockaddr_in from;
struct sigaction act_alarm;
struct sigaction act_int;
void alarm_handler(int);
void int_handler(int);
void set_sighandler();
void send_ping();
void recv_reply();
u16 checksum(u8 *buf, int len);
int handle_pkt();
void get_statistics(int, int);
void bail(const char *)
ping.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <errno.h>
#include <arpa/inet.h>
#include <signal.h>
#include <netinet/in.h>
#include "ping.h"
struct itimerval val_alarm={.it_interval.tv_sec = 1,
.it_interval.tv_usec = 0,
.it_value.tv_sec = 0,
.it_value.tv_usec = 1
};
int main(int argc, char **argv)
{
struct hostent *host;
if (argc < 2){
printf("Usuage: %s hostname\n", argv[0]);
exit(1);
}
if (host = gethostbyname(argv[1]) == NULL){
perror("can not understand the host name");
exit(1);
}
hostname = argv[1];
memset(&dest, 0, sizeof(dest));
dest.sin_family = PF_INET;
dest.sin_port = ntohs(0);
dest.sin_addr = *(struct in_addr *)host->h_addr_list[0];
if ((sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0){
perror("raw socket created error");
exit(1);
}
setuid(getuid());
pid = getpid();
set_sighandler();
printf("Ping %s(%s): %d bytes data in ICMP packets.\n\n",
argv[1], inet_ntoa(dest.sin_addr), datalen);
if ((setitimer(ITIMER_REAL, &val_alarm, NULL)) == -1)
bail("setitimer fails.");
recv_reply();
return 0;
}
void send_ping(void)
{
struct icmphdr *icmp_hdr;
int len;
icmp_hdr = (struct icmphdr *)sendbuf;
icmp_hdr->type = ICMP_ECHO;
icmp_hdr->code = 0;
icmp_hdr->icmp_id = pid;
icmp_hdr->icmp_seq = nsent++;
memset(icmp_hdr->data, 0xff, datalen);
gettimeofday((struct timeval *)icmp_hdr->data, NULL);
len = ICMP_HSIZE + datalen;
icmp_hdr->checksum = 0;
icmp_hdr->checksum = checksum((u8 *)icmp_hdr, len);
sendto(sockfd, sendbuf, len, 0, (struct sockaddr *)&dest, sizeof(dest));
}
void recv_reply()
{
int n, len;
int errno;
n = nrecv = 0;
len = sizeof(from);
while (nrecv < 3){
if ((n = recvfrom(sockfd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr *)&from, &len)) < 0){
if (errno == EINTR)
continue;
bail("recvfrom error");
}
gettimeofday(&recvtime, NULL);
if (handle_pkt())
continue;
nrecv++;
}
get_statistics(nsent, nrecv);
}
u16 checksum(u8 *buf, int len)
{
u32 sum = 0;
u16 *cbuf;
cbuf = (u16 *)buf;
while (len > 1){
sum += *cbuf++;
len -= 2;
}
if(len)
sum += *(u8 *)cbuf;
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return -sum;
}
int handle_pkt()
{
struct iphdr *ip;
struct icmphdr *icmp;
int ip_hlen;
u16 ip_datalen;
double rtt;
struct timeval *sendtime;
ip = (struct iphdr *)recvbuf;
ip_hlen = ip->hlen << 2;
ip_datalen = ntohs(ip->tot_len) - ip_hlen;
icmp = (struct icmphdr *)(recvbuf + ip_hlen);
if (checksum(u8 *)icmp, ip_datalen)
return -1;
if(icmp->icmp_id != pid)
return -1;
sendtime = (struct timeval *)icmp->data;
rtt = ((&recvtime)->tv_sec - sendtime->tv_sec)*1000 + ((&recvtime)->tv_usec - sendtime->tv_usec)/1000.0;
printf("%d bytes from %s: icmp_seq = %u ttl=%d rtt=%.3f ms\n",
ip_datalen,
inet_ntoa(from.sin_addr),
icmp->icmp_seq,
ip->ttl,
rtt);
return 0;
}
void set_sighandler()
{
act_alarm.sa_handler = alarm_handler;
if (sigaction(SIGALRM, &act_alarm, NULL) == -1)
bail("SIGALRM handler setting fails.");
act_int.sa_handler = int_handler;
if (sigaction(SIGINT, &act_int, NULL) == -1)
bail("SIGINT handler setting fails.");
}
void get_statistics(int nsent, int nrecv)
{
printf("---%s ping statistics ---\n", inet_ntoa(dest.sin_addr));
printf("%d packets transmitted, %d received, %0.0f%%" "packet loss\n",
nsent, nrecv, 1.0*(nsent - nrecv)/nsent*100);
}
void bail(const char *on_what)
{
fputs(strerror(errno), stderr);
fputs(":", stderr);
fputs(on_what, stderr);
fputc('\n', stderr);
exit(1);
}
void int_handler(int sig)
{
get_statistics(nsent, nrecv);
close(sockfd);
exit(1);
}
void alarm_handler(int signo)
{
send_ping();
}
icmp的程序(ping的实现)的更多相关文章
- TCP/IP详解学习笔记(4)-ICMP协议,ping和Traceroute
1.IMCP协议介绍 前面讲到了,IP协议并不是一个可靠的协议,它不保证数据被送达,那么,自然的,保证数据送达的工作应该由其他的模块来完成.其中一个重要的模块就是ICMP(网络控制报文)协议. 当传送 ...
- 4.ICMP协议,ping和Traceroute
1.IMCP协议介绍 前面讲到了,IP协议并不是一个可靠的协议,它不保证数据被送达,那么,自然的,保证数据送达的工作应该由其他的模块来完成.其中一个重要的模块就是ICMP(网络控制报文)协议. 当传送 ...
- UNIX网络编程——利用ARP和ICMP协议解释ping命令
一.MTU 以太网和IEEE 802.3对数据帧的长度都有限制,其最大值分别是1500和1492字节,将这个限制称作最大传输单元(MTU,Maximum Transmission Unit) ...
- 利用 Linux tap/tun 虚拟设备写一个 ICMP echo 程序
本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. 前面两篇文章已 ...
- 利用ARP和ICMP协议解释ping命令
一.MTU 以太网和IEEE 802.3对数据帧的长度都有限制,其最大值分别是1500和1492字节,将这个限制称作最大传输单元(MTU,Maximum Transmission Unit).如果IP ...
- TCP/IP详解学习笔记(4)-ICMP协议,ping和Traceroute【转】
转自:http://blog.csdn.net/goodboy1881/article/details/670761 1.IMCP协议介绍 前面讲到了,IP协议并不是一个可靠的协议(是一种尽力传送的协 ...
- 【网络协议】ICMP协议、Ping、Traceroute
ICMP协议 ICMP常常被觉得是IP层的一个组成部分,它是网络层的一个协议.它传递差错报文以及其它须要注意的信息.ICMP报文通常被IP层或更高层(TCP.UDP等)使用,它是在IP数据报内 ...
- 计算机网络(5)-----ICMP协议和PING程序
控制报文协议(Internet Control Message Protocol) 定义 它是TCP/IP协议族的一个子协议,用于在IP主机.路由器之间传递控制消息.控制消息是指网络通不通.主机是否可 ...
- 应用程序PING发出的是什么报文?
Ping位于用户层,一般用来测试一台主机是否可达,该程序发送一份ICMP回显请求报文给主机,并等待返回ICMP回显 应答
随机推荐
- 浅析 Node.js 的 vm 模块以及运行不信任代码
在一些系统中,我们希望给用户提供插入自定义逻辑的能力,除了 RPC 和 REST 之外,运行客户提供的代码也是比较常用的方法,好处是可以极大地减少在网络上的耗时.JavaScript 是一种非常流行而 ...
- ssh 远程执行绝对路径命令mysqld_multi 报my_print_defaults不存在
通过SSH直接执行远程命令(这种方式会使用Bash的non-interactive + non-login shell模式)找不到命令参考:http://ghoulich.xninja.org/201 ...
- bootstrap 中dropmenu不起作用
今天在使用bootstrap发现dropmenu一直不起作用,代码是从官网拷贝过来. 网上查找可以用的页面进行一点点的去除分析,发现竟然是顺序反了导致的. 在使用dropmenu时需要引入jquery ...
- 再谈 Go 语言在前端的应用前景
12 月 23 日,七牛云 CEO & ECUG 社区发起人许式伟先生在 ECUG Con 2018 现场为大家带来了主题为<再谈 Go 语言在前端的应用前景>的内容分享. 本文是 ...
- UVA 10003 Cutting Sticks(区间dp)
Description Cutting Sticks You have to cut a wood stick into pieces. The most affordable company ...
- 关于Metadata Client Object Model 的一些操作
一.查询指定的Termset及子项 <script type="text/javascript" src="/Style%20Library/aaaa/Script ...
- 远征(expedition)
[题目描述] 寒枫将军将要带领他的部队去圣雪山消灭那里的冰龙. 部队分成了若干个小队,属于同一个小队的人兵种相同.寒枫将军有着杰出的指挥能力,在战斗的时候,寒枫将军能够让所有相同兵种的人互相配合,使t ...
- Codeforces 895C Square Subsets(状压DP 或 异或线性基)
题目链接 Square Subsets 这是白书原题啊 先考虑状压DP的做法 $2$到$70$总共$19$个质数,所以考虑状态压缩. 因为数据范围是$70$,那么我们统计出$2$到$70$的每个数的 ...
- Codeforces 875C National Property(拓扑排序)
题目链接 National Property 给定n个单词,字符集为m 现在我们可以把其中某些字母变成大写的.大写字母字典序大于小写字母. 问是否存在一种方案使得给定的n个单词字典序不下降. 首先判 ...
- Xamarin.Forms单元控件Cell
Xamarin.Forms单元控件Cell 单元控件Cell是Xamarin.Forms为ListView和TableView专门定制的一类项目元素.它包括5个控件,分别为文本框单元EntryCe ...