【问题标题】:C program to get the values of IP header fields from Linux IP stackC程序从Linux IP堆栈中获取IP头字段的值
【发布时间】:2011-07-14 05:41:57
【问题描述】:

我正在开发一个程序,我需要知道我的程序中 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 程序中?

【问题讨论】:

  • 您是否想知道如何从已经可用的数据包中解析字段,或者如何首先捕获包含标头的数据包?
  • 我建议看看libpcap - 它应该会让你的生活更轻松。
  • 查询是我怎样才能得到这些系统值,因为在创建一个简单的数据报包(UDP)时,我填充了 SrcIP 和端口,Dest IP 地址和端口并发送数据包,其余的默认情况下从系统堆栈中选择值。所以我想知道其余字段的值,例如:ttl、tos 等

标签: c


【解决方案1】:

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

struct ipheader *iph = (struct ipheader *)blk;
printf ("TTL = %d\n", 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 = %x\n", iph->ip_ttl);
    printf ("sum = %x\n", iph->ip_sum);
    printf ("dst = %x\n", iph->ip_dst);

    return 0;
}

输出如预期:

TTL = 55
sum = 7777
dst = 99999999

【讨论】:

  • 基本上我提供的结构仅供参考,真正的问题是我怎样才能获得这些系统值,因为在创建一个简单的数据报包(UDP)时,我填写了 SrcIP 和端口,Dest IP 地址和端口并发送数据包,其余值默认从系统堆栈中选取。其余值包括 ip_ttl、ip_tos 等
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    获取 TTL 值:

    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 %d\n", opt_val);
    

    设置TTL值:

    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));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-20
      相关资源
      最近更新 更多