ping程序:ip 发送一个icmp回射请求,该节点以一个icmp回射应答。ipv4,ipv6点格式:
0 7 8 15 16 31
type | code | 校验和 |
表示符 | 表示符 | 序列号 |
data | data | data |
表示符一般会设置为----- pid
#include "ping.h" | |
/* | |
ipv4-icmp 发送数据函数 | |
*/ | |
void send_v4(void) | |
{ | |
int len; | |
struct icmp*icmp; | |
icmp=(struct icmp *)sendbuf; | |
icmp->icmp_type=ICMP_ECHO; | |
icmp->icmp_code=0; | |
icmp->icmp_id=pid; | |
icmp->icmp_seq=nsent++; | |
memset(icmp->icmp_data,0x5a,datalen);//初始化 | |
gettimeofday((structtimeval *)icmp->icmp_data,NULL); | |
len=8+datalen; | |
icmp->icmp_cksum=in_cksum((uint16_t *)icmp,len); | |
sendto(sockfd,sendbuf,len,0,pr->sasend,pr->salen); | |
} | |
其实主要是icmpv6:
void send_v6(void) | |
{ | |
#ifdef IPV6 | |
int len; | |
struct icmp6_hdr * icmp6; | |
icmp6=(strcut icmp6_hdr*)sendbuf; | |
icmp6->icmp6_code=0; | |
icmp6->icmp6_type=ICMP6_ECHO_REQUEST; | |
icmp6->icmp6_id=pid; | |
icmp6->icmp6_seq=nsent++; | |
memset((icmp6+1),0x5a,datalen); | |
gettimeofday((structtimeval*)(icmp6+1),NULL); | |
len=8+datalen; | |
sendto(sockfd,sendbuf,len,0,pr->sasend,pr->salen); | |
#endif | |
} |
mian.c
#include "ping.h"
//赋值ipv4 ipv6
struct proto proto_v4={proc_v4,send_v4,NULL,NULL,0,IPPROTO_ICMP};
#ifdef IPV6
struct proto proto_v6={proc_v6,send_v6,NULL,NULL,0,IPPROTO_ICMPV6};
#endif
int datalen=56;
//icmp的大小
int main(int argc, char *argv[])
{
int c;
struct addrinfo *ai;
char *h;
opterr=0;
while((c=getopt(argc,argv,"v"))!=1)
{
switch(c)
{
case 'v':
verbose++;
break;
case '?':
err_quit("error parament !");
}
}
if(optind!=argc-1)
err_quit("usage : ping [-v]
");
host=argv[argc-1];
pid=getpid() & 0xffff;
ai=host_serv(host,NULL,0,0);
h=inet_ntop_host(ai->ai_addr,ai->ai_addrlen);
printf("PING %s (%s):%d data bytes\n",ai->ai_canonname?ai->ai_canonname:h,h,datalen);
if(ai->ai_family==AF_INET)
{
pr=&proto_v4;
#ifdef IPV6
}else if(ai->ai_family==AF_INET6)
{
pr=&proto_v6;
if(IN6_IS_ADDR_V4MAPPED( &(((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr )))
err_quit("error : IPV6");
#endif
}
else
err_quit("nothing i know!");
pr->sasend=ai->ai_addr;
pr->sarecv=calloc(1,ai->ai_addrlen);
pr->salen=ai->ai_addrlen;
readloop();
return 0;
}
具体的icmp的原理过程,我认为参考一下tcp/ip [RFC0792][ RFC443],自己写着玩的一个烂代码,同时也是来源unix网络编程数据。自己好low才玩github没有多久,代码地址:
https://github.com/xiaozw1994/library-libs.git 这只是参考而已;
2、分享一个gcc编译多文件的方法:
1、gcc -o test.o main.c test.c //一般两个文件没有问题,具体意思大家都知道哈
2、对于多文件变异是gcc 多个文件会报错:not support mutil-file ,大概是这个意思哈:此时要用一下命令:
gcc -shared file.c -o file.o
gcc main.c -lfile.o -L path//路径要是绝对地址
3、如果文件多是还可以引入make命令,make -f make.debug 等,linux下的make 来进行;
4、当然也可以用写一个编译的脚本shell python,其实用C语言的 execl 写一个编译的命令也是可以的