C程序从Linux IP栈中获取IP报头字段的值

  • 本文关键字:IP 报头 字段 获取 程序 Linux
  • 更新时间 :
  • 英文 :


我正在开发一个程序,我需要知道我的程序内的IP头字段的值。由于IP报头是20字节:

struct ipheader {
     unsigned char ip_hl:4, ip_v:4; /* this means that each member is 4 bits */
     unsigned char ip_tos;
     unsigned short int ip_len;
     unsigned short int ip_id;
     unsigned short int ip_off;
     unsigned char ip_ttl;
     unsigned char ip_p;
     unsigned short int ip_sum;
     unsigned int ip_src;
     unsigned int ip_dst;
    }; 

有任何方法,我可以知道这些字段的值在我的C程序里?

如果编译器没有在该结构中引入任何对齐块(确保CHAR_BIT为8,sizeof(struct ipheader)为20),您应该能够将其原样包含在代码中,然后添加如下内容:

struct ipheader *iph = (struct ipheader *)blk;
printf ("TTL = %dn", iph->ip_ttl);

在该代码中,您将有一个由blk指向的IP头,这可能是char*。将其转换为正确的指针类型将允许您轻松访问字段。

下面的完整程序展示了这一点:

#include <stdio.h>
#include <limits.h>
struct ipheader {
    /* 0 */ unsigned char ip_hl:4, ip_v:4;
    /* 1 */ unsigned char ip_tos;
    /* 2 */ unsigned short int ip_len;
    /* 3 */ unsigned short int ip_id;
    /* 4 */ unsigned short int ip_off;
    /* 5 */ unsigned char ip_ttl;
    /* 6 */ unsigned char ip_p;
    /* 7 */ unsigned short int ip_sum;
    /* 8 */ unsigned int ip_src;
    /* 9 */ unsigned int ip_dst;
};
int main (void) {
    char blk[] = {
        'x00','x11','x22','x22','x33','x33','x44','x44',
        'x55','x66','x77','x77','x88','x88','x88','x88',
        'x99','x99','x99','x99'
    };
    struct ipheader *iph = (struct ipheader *)(&blk);
    printf ("TTL = %xn", iph->ip_ttl);
    printf ("sum = %xn", iph->ip_sum);
    printf ("dst = %xn", iph->ip_dst);
    return 0;
}

输出如下所示:

TTL = 55
sum = 7777
dst = 99999999

其中一些值可以通过SOL_IP/IPPROTO/IP级别的setsockopt()/getsockopt()调用来设置/检索。参考您的操作系统文档(例如:Linux man 7 ip)

您应该使用setsockopt/getsockopt例程与套接字机制进行接口。这些函数在不同的级别上运行(IPPROTO_IP, IPPROTO_TCP等),一些选项仅适用于特定的套接字类型(例如选项IP_TTL仅适用于AF_INET套接字)。

get TTL value:

int sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
unsigned int opt_val;                                                         
unsigned int opt_len;                                                       
getsockopt(sock, IPPROTO_IP, IP_TTL, &opt_val, &opt_len);
printf("ttl %dn", opt_val);

set TTL value:

int sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
unsigned char ttl_val = 32;                                                                                                                                        
setsockopt(sock, IPPROTO_IP, IP_TTL, &ttl_val, sizeof(ttl_val));

最新更新