Linux C 实现最简单的ICMP_ECHO请求报文发送

来源:互联网 发布:求不定积分的软件 编辑:程序博客网 时间:2024/05/02 04:26

弄了两天,终于搞定了!把最简单的icmp报文发送实现了。本程序在linux环境编写,使用原始套接字。

实现步骤:

1、得到protocol实体(protoent,声明于<netdb.h>);

2、初始化地址结构(sockaddr_in,声明于<netinet/in.h>);

3、创建套接字(socket(),声明于<sys/socket.h>,参数声明于<sys/types.h>);

4、更改socket选项,更改发送缓冲区大小(setsockopt(),声明于<sys/socket.h><sys/types.h>);

5、发送报文(sendto(),声明于<sys/types.h><sys/socket.h>);

6、关闭socket描述符(close(),声明于<unistd.h>);


代码:

#include <unistd.h>#include <sys/types.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#include <netinet/ip_icmp.h>#include <netinet/ip.h>#include <arpa/inet.h>typedef unsigned char byte;typedef unsigned long ulong;typedef unsigned short ushort;const char* proto_name="icmp";const char* ip_str="10.14.4.167";#define SEND_BUFF1024#define CK_NULL(___ent,___str)({\if(___ent==NULL)printf(___str);\})#define PRT_ADDR_TEST(___addr)({\printf("direction ip is:%d.%d.%d.%d\r\n",\(___addr&0x000000ff),   \(___addr&0x0000ff00)>>8,\(___addr&0x00ff0000)>>16,\(___addr&0xff000000)>>24\);\})bytesend_buffer[SEND_BUFF];// declare functionushorticmp_cal_cksum(byte*,int);voidicmp_create(){struct icmp* icmph=(struct icmp*)send_buffer;int pid,i,data_len;pid=getuid();data_len=SEND_BUFF-8;// send_length sub icmp header_lengthicmph->icmp_type=ICMP_ECHO;icmph->icmp_code=0;icmph->icmp_cksum=0;icmph->icmp_seq=0;icmph->icmp_id=pid;for(i=0;i<data_len;i++)icmph->icmp_data[i]=i;icmph->icmp_cksum=icmp_cal_cksum((byte*)icmph,data_len);}ushorticmp_cal_cksum(byte* _data,int _data_len){int sum=0;int odd=_data_len&0x01;ushort* value=(ushort*)_data;while(_data_len& 0xfffe){sum+=*(ushort*)_data;_data+=2;_data_len-=2;}if(odd){ushort tmp=((*_data)<<8)&0xff00;sum+=tmp;}sum=(sum>>16)+(sum&0xffff);sum+=(sum>>16);return ~sum;}intmain(int argc,char** argv){// socket fdint sockfd;// return err codeint err_code;// send data lengthint snd_len;// long addrulong addr_l;// protocol entitystruct protoent* protocol;// socket send buffer lengthint send_buff=SEND_BUFF;// protocol socket address struct sockaddr_in dest_addr;// get protocol entity protocol=getprotobyname(proto_name);CK_NULL(protocol,"error! cannot get protocol entity!!!\r\n");// convert ip str to u_longaddr_l=inet_addr(ip_str);if(addr_l==INADDR_NONE){printf("error! cannot convert ip str to long addr!!!\r\n");return -1;}addr_l=htonl(addr_l);PRT_ADDR_TEST(addr_l);// set memory 0bzero((char*)&dest_addr,sizeof(dest_addr));// full sockaddr_in structmemcpy((char*)&dest_addr.sin_addr,&addr_l,sizeof(addr_l));sockfd=socket(AF_INET,SOCK_RAW,protocol->p_proto);if(sockfd<0){printf("error!cannot create sockfd!\r\n");return -1;}err_code=setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&send_buff,sizeof(send_buff));icmp_create();snd_len=sendto(sockfd,send_buffer,send_buff,0,(struct sockaddr*)&dest_addr,sizeof(dest_addr));if(snd_len<send_buff){printf("error!send data length is not enougth!\r\n");return -1;}printf("data has sended length=%d\r\n",snd_len);close(sockfd);return 0;}
注:创建原始套接字时应使用管理员权限,否则会创建失败!好像也有代码中获取权限的方法,但我没有去查相关资料。

0 0
原创粉丝点击