C 全局变量值不保存在函数之外

标签 c static global-variables uint32-t

我遇到了一个有点尴尬的问题:我有一个带有两个全局 uint32_t 变量的程序,以及一个为它们赋值的函数。然而,当我稍后尝试打印/访问这些值时,一个给了我正确的值,而另一个仍然为零!我很困惑。这是代码:

#include <stdio.h>
#include <stdlib.h>
#include <libnet.h>
#include <stdint.h>
#include <pcap.h>
#include <time.h>
#include <string.h>
#include <arpa/inet.h>

static uint32_t last_seq; 
static uint32_t seq_offset;


void packet_handler(u_char* user, const struct pcap_pkthdr *header, const u_char * packet){
  struct tcphdr *tcp = (struct tcphdr *) (packet + LIBNET_IPV4_H + LIBNET_ETH_H);

  printf("current seq = %u\n", ntohl((uint32_t)(tcp->seq)));
  printf("last seq = %u\n", last_seq);
  printf("difference in seq = %u\n", ntohl((uint32_t)(tcp->seq)) - last_seq);
  last_seq = ntohl((uint32_t)(tcp->seq));

  seq_offset = ntohl((uint32_t)(tcp->seq)) - last_seq;
}

void seqno_probe(){
  libnet_t *l;
  u_int32_t dst_addr;
  u_int32_t src_addr;
  char *device = "eth0";
  char errbuf[LIBNET_ERRBUF_SIZE];
  libnet_ptag_t tcp = 0;
  libnet_ptag_t ip4 = 0;
  char *filter = "(tcp[13] == 0x14) || (tcp[13] == 0x12)";
  pcap_t *handle; 
  char libpcap_errbuf[PCAP_ERRBUF_SIZE];
  struct bpf_program fp;
  bpf_u_int32 netp, maskp;
  int answer, i;
  time_t tv;

  l = libnet_init(LIBNET_RAW4, device , errbuf);
  if(l == NULL){
    fprintf(stderr, "libnet_init() failed: %s\n", errbuf);
    libnet_destroy(l);
    exit(EXIT_FAILURE);
  }


  /* IP address */

  dst_addr = libnet_name2addr4(l, "172.16.54.5", LIBNET_DONT_RESOLVE);

  if(dst_addr == -1){
    fprintf(stderr, "Error converting IP address.\n");
    libnet_destroy(l);
    exit(EXIT_FAILURE);
  }

  src_addr = libnet_name2addr4(l, "172.16.54.3", LIBNET_DONT_RESOLVE);
if(src_addr == -1){
    fprintf(stderr, "Couldn't get own IP address: %s\n", libnet_geterror(l));
    libnet_destroy(l);
    exit(EXIT_FAILURE);
  }

  handle = pcap_open_live(device, 1500, 0, 2000, libpcap_errbuf);
  if(handle == NULL){
    fprintf(stderr, "Error opening pcap handle: %s\n", libpcap_errbuf);
    libnet_destroy(l);
    exit(EXIT_FAILURE);
  }

  if((pcap_setnonblock(handle, 1, libpcap_errbuf)) == -1){
    fprintf(stderr, "Error setting nonblock: %s\n", libpcap_errbuf);
    libnet_destroy(l);
    exit(EXIT_FAILURE);
  }

  if(pcap_lookupnet(device, &netp, &maskp, libpcap_errbuf) == -1){
    fprintf(stderr, "Net lookup error: %s\n", libpcap_errbuf);
    libnet_destroy(l);
    exit(EXIT_FAILURE);
  }

  if(pcap_compile(handle, &fp, filter, 0, maskp) == -1){
    fprintf(stderr, "BPF error: %s\n", libpcap_errbuf);
    libnet_destroy(l);
    exit(EXIT_FAILURE);
  }
if(pcap_setfilter(handle, &fp) == -1){
    fprintf(stderr, "Error setting BPF: %s\n", libpcap_errbuf);
    libnet_destroy(l);
    exit(EXIT_FAILURE);
  }

  pcap_freecode(&fp);

  tcp = libnet_build_tcp(
        libnet_get_prand(LIBNET_PRu16), /*source port*/
        514,                            /*destination port */
        libnet_get_prand(LIBNET_PRu16),/*sequence number */
        0,                              /*ack*/ 
        TH_SYN,                         /*control flag*/ 
        7,                              /*window*/
        0,                              /*checksum*/
        0,                              /*urgent*/ 
        LIBNET_TCP_H,                   /*header length*/ 
        NULL,                           /*payload*/ 
        0,                              /*payload length*/
        l,                              /*libnet context*/ 
        tcp                             /*protocol tag*/
        );

  if(tcp == -1){ 
    fprintf(stderr,"Error building TCP header: %s\n", libnet_geterror(l));
    libnet_destroy(l);
    exit(EXIT_FAILURE);
  }


  ip4 = libnet_build_ipv4(
      LIBNET_TCP_H + LIBNET_IPV4_H,     /*length*/
      0,                                /*TOS*/
      libnet_get_prand(LIBNET_PRu16),   /*IP ID*/
      0,                                /*frag offset*/
      127,                              /*TTL*/
      IPPROTO_TCP,                      /*upper layer protocol*/
      0,                                /*checksum*/
      src_addr,                         /*src ip address*/
      dst_addr,                         /*dest ip address*/
      NULL,                             /*payload*/
      0,                                /*payload length*/
      l,                                /*libnet context*/
      ip4                               /*protocol tag*/
      ); 

  if(ip4 == -1){
    fprintf(stderr, "Error building IP4 header: %s\n", libnet_geterror(l));
    libnet_destroy(l);
    exit(EXIT_FAILURE);
  }

  for(i=0;i<2;i++){
    if(libnet_write(l) == -1){
      fprintf(stderr, "Unable to send packet: %s\n", libnet_geterror(l));
      libnet_destroy(l);
      exit(EXIT_FAILURE);
    }
 answer = 1;
    tv     = time(NULL);

    while(answer){
      pcap_dispatch(handle, -1, packet_handler, NULL);
      if((time(NULL) - tv) > 2){
        answer = 0;
      }
    }
  }
  libnet_destroy(l);
}


int main(){
  seqno_probe();
  printf("last_seq = %u\n seq_offset = %u\n", last_seq, seq_offset);
  return 0;
}

当我运行此命令时,last_seq 的输出是正确的,但 seq_offset 仍然为零! 任何帮助将不胜感激:)。

问候,

莱纳斯

最佳答案

好的,我做出正确的回答。

为什么 seq_offset 会改变?基本上每次调用时都将其分配为 0。

last_seq = ntohl((uint32_t)(tcp->seq));
seq_offset = ntohl((uint32_t)(tcp->seq)) - last_seq;

将计算为seq_offset = ntohl((uint32_t)(tcp->seq)) - ntohl((uint32_t)(tcp->seq)),始终为0。

你必须反转线条

seq_offset = ntohl((uint32_t)(tcp->seq)) - last_seq;
last_seq = ntohl((uint32_t)(tcp->seq));

这样,last_seq 包含最后一个值。

关于C 全局变量值不保存在函数之外,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16152496/

相关文章:

c# - c转c#(使用smem的libvlc方法)

php - 在 PHP 中访问单例方法

c - 隐藏的全局变量是不好的编程习惯吗?

C 回显用户输入

python - 在cython中使用C函数读写文件中的数组

c++ - 如何避免 C++ 派生类中基类成员的重复拷贝

c++ - 如何描述在 C++ 中使用全局变量的所有情况?

python - 通过类更改变量值(python)

c - 在调用 mmap 后我是否需要保持文件打开?

javascript - django 如何在模板中包含 javascript