IP数据包的格式
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IP数据包的格式相关的知识,希望对你有一定的参考价值。
参考技术A
TCP或IP协议定义了一个在因特网上传输的包,称为IP数据报,而IP数据报是个比较抽象的内容,是对数据包的结构进行分析。
一个IP数据报由首部和数据两部分组成。首部的前一部分是所有IP数据报都必须包含的20字节固定长度,后面是一些可选字段。其中20字节的固定长度包括4位的版本号,4位的首部长度,8位的区分服务,16位的数据报总长度,16位的标识,3位的标志,13位片偏移,8位生存时间,8位协议,16位首部检验和,32位源地址和32位目的地址。
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;
}
以上是关于IP数据包的格式的主要内容,如果未能解决你的问题,请参考以下文章
网络层IP数据包和ARP协议转发原理
关于ICMP数据包的问题
九度oj 题目1475:IP数据包解析
c_cpp 使用原始套接字发送和接收带有ICMP协议的OUTPUT的数据包的小程序是六进制格式的数据包。可以打印为%c来查看数据。 IP heade
RFC1055:在串行线路上传输ip数据包的非标准协议
网络层协议介绍及概述