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

时间:2013-04-22 16:52:42

标签: 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保持为零! 任何帮助将不胜感激:)。

此致

莱纳斯

2 个答案:

答案 0 :(得分:3)

好的,我做了一个正确的答案。

为什么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包含最后一个值。

答案 1 :(得分:0)

tristopia在评论中指出了答案,我担心这是相当尴尬的。我通过切换两个赋值语句来修复它

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

谢谢!