c_cpp 使用原始套接字发送和接收带有ICMP协议的OUTPUT的数据包的小程序是六进制格式的数据包。可以打印为%c来查看数据。 IP heade
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c_cpp 使用原始套接字发送和接收带有ICMP协议的OUTPUT的数据包的小程序是六进制格式的数据包。可以打印为%c来查看数据。 IP heade相关的知识,希望对你有一定的参考价值。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <inttypes.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
unsigned short checksumCalc(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;
}
int main(int argc, char **argv)
{
uint8_t *packet;
packet = malloc(500);
struct ip ip;
ip.ip_hl = 0x5;
ip.ip_v = 0x4;
ip.ip_tos = 0x0;
ip.ip_len = htons(60);
ip.ip_id = htons(12830);
ip.ip_off = 0x0;
ip.ip_ttl = 1;
ip.ip_p = IPPROTO_ICMP;
ip.ip_sum = 0x0;
ip.ip_src.s_addr = inet_addr("192.168.74.57");
ip.ip_dst.s_addr = inet_addr("192.168.74.58");
ip.ip_sum = checksumCalc((unsigned short *)&ip, sizeof(ip));
memcpy(packet, &ip, sizeof(ip));
struct icmp icmp;
icmp.icmp_type = 8; // 8 means ICMP_ECHO
icmp.icmp_code = 0;
icmp.icmp_id = 1000;
icmp.icmp_seq = 0;
char icmpData[500];
char msg[500]="helloworld";
/*printf("Enter the data you want to send: \n");*/
/*fgets(msg, 499, stdin);*/
// first: doing it to calculate checksum
memcpy(icmpData, &icmp, 8);
memcpy(icmpData + 8, msg, strlen(msg));
icmp.icmp_cksum = checksumCalc((short unsigned int*)&icmpData, 8 + strlen(msg));
// second: doing it to include the checksum in the packet this time
memcpy(icmpData, &icmp, 8);
memcpy(icmpData + 8, msg, strlen(msg));
memcpy(packet + 20, icmpData, 8 + strlen(msg));
int sock;
if ((sock = socket(AF_INET, SOCK_RAW, 1)) < 0) { // 1 for icmp
perror("Error creating socket. Are you root? \n");
exit(1);
}
const int on = 1;
if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0) {
perror("Couldn't set socket options. \n");
exit(1);
}
struct sockaddr_in send;
//memset(&sin, 0, sizeof(sin));
send.sin_family = AF_INET;
send.sin_port = 0;
send.sin_addr.s_addr = ip.ip_dst.s_addr;
struct sockaddr receive;
uint32_t receiveSize;
uint8_t *receivePacket = malloc(500);
int sent =sendto(sock, packet, 60, 0, (struct sockaddr *)&send, sizeof(struct sockaddr));
if (sent < 0) {
perror("Failed to send. \n");
exit(1);
}
int response = recvfrom(sock, receivePacket, 60, 0, &receive, &receiveSize);
struct iphdr *ih = (struct iphdr*)receivePacket;
struct icmphdr *ich =(struct icmphdr*) (receivePacket+sizeof(struct iphdr));
printf("protocal %d\n",ih->version);
if(response > 0)
{
unsigned int i;
for(i=0;i<60;++i){
printf("%02x ",receivePacket[i]);
}
}
/*}*/
return 0;
}
以上是关于c_cpp 使用原始套接字发送和接收带有ICMP协议的OUTPUT的数据包的小程序是六进制格式的数据包。可以打印为%c来查看数据。 IP heade的主要内容,如果未能解决你的问题,请参考以下文章
发送Icmp消息但什么都没有收到?
原始套接字的学习和问题
Python Raw Socket 无法接收 ICMP 消息;出现在 Wireshark 中
在 ICMP 套接字上接收数据
原始套接字编程
SOCK_RAW编程