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数据包的非标准协议

网络层协议介绍及概述