📄 dyn_iwspy_rec.c
字号:
/* $Id: dyn_iwspy_rec.c,v 1.13 2000/04/06 07:26:52 jm Exp $ * Dynamics iwspy recorder module * * Dynamic hierarchial IP tunnel * Copyright (C) 1998-2000, Dynamics group * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See README and COPYING for * more details. */#include <stdlib.h>#include <errno.h>#include <string.h>#include <assert.h>#include <asm/types.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <arpa/inet.h>#include <netinet/in.h>#include <linux/wireless.h>#include "util.h"#include "hashtable.h"#include "dyn_iwspy_rec.h"#include "debug.h"#ifndef TRUE#define TRUE 1#endif#ifndef FALSE#define FALSE 0#endif#define DEBUG_FLAG '5'/* gnuplot headers */#define IMG_X 1000 /* single node image */#define IMG_Y 300#define G_IMG_X 1500 /* group node image */#define G_IMG_Y 400#define Q_RANGE 100 /* quality range: 0 - Q_RANGE */static struct hashtable *rec_hash;static int rec_num;struct timeval start_time;int new_dump = 1;static int hashfunc(void *key, const int hashsize){ __u8 hash; __u32 data; data = *((__u32 *) key); /* 32 least significant bytes of the mac address */ hash = (__u8)((data & 0xff000000) >> 24) ^ (__u8)((data & 0x00ff0000) >> 16) ^ (__u8)((data & 0x0000ff00) >> 8) ^ (__u8)(data & 0x000000ff); return ((int) hash);}/* * Comparison function for hashtable * * Arguments: * key First data structure * cmprd Second data structure * * Return: * 0 Not equal * 1 Equal */static int cmpfunc(void *key, struct node *cmprd){ __u32 data1; struct hw_record *data2; if (key == NULL) { DEBUG(DEBUG_FLAG, "rec, cmpfunc:\n" "value for argument 'key' was NULL !\n" "Illegal value, returning 0 ! \n"); return 0; } if (cmprd == NULL) { DEBUG(DEBUG_FLAG, "rec, cmpfunc:\n" "value for argument 'cmpd' was NULL !\n" "Illegal value, returning 0 ! \n"); return 0; } data1 = *((__u32 *)key); data2 = (struct hw_record *) cmprd; /* Compare the 32 least significant bits of the mac address */ if (!memcmp(&data1, &data2->hw[2], sizeof(__u32))) return 1; return 0;}int rec_init(void){ /* initialize hash */ rec_num = 0; rec_hash = NULL; rec_hash = hashtable_init(REC_HASH_SIZE); if (rec_hash == NULL) return -1; return 0;}int rec_clean(struct node *node, void *data){ struct hw_record *entry = (struct hw_record *) node; struct qual_entry *list = entry->quals; struct qual_entry *tmp; DEBUG(DEBUG_FLAG, "rec_clean\n"); while (list != NULL) { tmp = list; list = list->next; free(tmp); } hashtable_remove(node); free(entry); new_dump = 1; return 1;}void rec_clean_up(void){ DEBUG(DEBUG_FLAG, "rec_clean_up\n"); if (rec_hash == NULL) return; hashtable_iterator(rec_hash, rec_clean, NULL); hashtable_destroy(rec_hash); rec_hash = NULL;}static struct qual_entry *alloc_qual_entry(void){ struct qual_entry *qual; qual = (struct qual_entry *) malloc(sizeof(struct qual_entry)); if (!qual) { DEBUG(DEBUG_FLAG, "alloc_qual_entry: malloc failed\n"); return NULL; } memset(qual, 0, sizeof(struct qual_entry)); return qual;}/* Add new quals node to old mac entry */static int qual_add(struct hw_record *rec, struct iw_quality *qual, struct timeval *t){ struct qual_entry *entry; unsigned int c; if (!rec->quals) { /* first qual entry? */ rec->quals = alloc_qual_entry(); if (!rec->quals) { DEBUG(DEBUG_FLAG, "qual_add:" "alloc_qual_entry failed\n"); return -1; } rec->tail = rec->quals; } else if (rec->tail->current >= REC_NODE_CHUNK) { DEBUG(DEBUG_FLAG, "qual_add: New CHUNK\n"); /* time to allocate one chunk more */ rec->tail->next = (struct qual_entry *) malloc(sizeof(struct qual_entry)); if (!rec->tail->next) { DEBUG(DEBUG_FLAG, "qual_add:" " malloc failed\n"); return -1; } rec->tail = rec->tail->next; memset(rec->tail, 0, sizeof(struct qual_entry)); } entry = rec->tail; c = entry->current; assert(c >= 0 && c <= REC_NODE_CHUNK); /* vector structure */ if (qual->qual > 200) entry->qual[c].qual = 0; else entry->qual[c].qual = qual->qual; entry->qual[c].level = qual->level; entry->qual[c].noise = qual->noise; entry->tstamp[c].tv_sec = t->tv_sec; entry->tstamp[c].tv_usec = t->tv_usec; entry->current++; DEBUG(DEBUG_FLAG, "qual_add: %s - %d\n", inet_ntoa(rec->ip_addr), entry->current); return 0;}int rec_add_qual(char *hw, struct iw_quality *qual, struct timeval *tstamp){ struct hw_record *recs; int ret; assert(rec_hash != NULL); recs = (struct hw_record *) hashtable_fetch(rec_hash, hashfunc, &hw[2], cmpfunc); if (!recs) { DEBUG(DEBUG_FLAG, "rec_add_qual: record not found!\n"); return 1; } ret = qual_add(recs, qual, tstamp); if (ret < 0) DEBUG(DEBUG_FLAG, "rec_add_qual: qual entry add failed\n"); return ret;}int rec_add(char *hw, struct iw_quality *qual, struct timeval *t, struct in_addr addr) { struct hw_record *recs; int ret; if (new_dump) { new_dump = 0; start_time.tv_sec = t->tv_sec; start_time.tv_usec = t->tv_usec; DEBUG(DEBUG_FLAG, "rec_add: start time %ld\n", start_time.tv_sec); } assert(rec_hash != NULL); recs = (struct hw_record *) hashtable_fetch(rec_hash, hashfunc, &hw[2], cmpfunc); if (recs) { /* old mac found. Add to that */ ret = qual_add(recs, qual, t); if (ret < 0) DEBUG(DEBUG_FLAG, "rec_add: qual entry add failed " "(old mac)\n"); return ret; } /* mac not found. Add new one */ recs = (struct hw_record *) malloc(sizeof(struct hw_record)); if (!recs) { DEBUG(DEBUG_FLAG, "rec_add: malloc failed\n"); /* FIX: Add record dumping into files and free memory. Then initialize new list and continue recording. */ return -1; } memcpy(recs->hw, hw, ETH_ALEN); recs->ip_addr.s_addr = addr.s_addr; recs->quals = NULL; recs->tail = recs->quals; /* Add mac entry */ list_init_node(&recs->hashnode); ret = hashtable_add(rec_hash, hashfunc, &hw[2], &recs->hashnode); if (ret != TRUE) { DEBUG(DEBUG_FLAG, "rec_add: hashtable_add failed\n"); return -1; } rec_num++; /* Add new qual node to the mac entry */ ret = qual_add(recs, qual, t); if (ret < 0) { DEBUG(DEBUG_FLAG, "rec_add: qual entry add " "failed (new mac)\n"); return -1; } return ret;}int rec_add_long(struct sockaddr *hwa, unsigned char *hw, struct in_addr addr, struct iw_quality *qual, struct timeval *t, int monitored){ int index = -1, i; DEBUG(DEBUG_FLAG, "rec_add_long (%s)\n", inet_ntoa(addr)); for (i = 0 ; i < monitored; i++) { if (!(memcmp(hwa[i].sa_data, hw, ETH_ALEN))) index = i; } if (index < 0) { DEBUG(DEBUG_FLAG, "rec_add: MAC address not found\n"); return -1; } return (rec_add((char *)&(hwa[index].sa_data), &qual[index], t, addr));}/**********************//* Dump data to files *//**********************/static int dump_fa(struct node *node, void *data){ struct hw_record *rec = (struct hw_record *) node; struct qual_entry *qual = rec->quals; FILE *fd, *header; char name[FILENAME_MAX]; unsigned int i, len; unsigned long range_sec = 0, range_dmsec = 0;#ifdef TEST unsigned long diff;#endif long range_usec = 0; struct dump *info = (struct dump *)data; /* open file */ snprintf(name, FILENAME_MAX, "FA-%s-dump.dat", inet_ntoa(rec->ip_addr)); fd = fopen(name, "w"); if (!fd) { DEBUG(DEBUG_FLAG, "dump_fa: fopen: %s\n", strerror(errno)); return -1; } /* Print filetype info */ fprintf(fd, "# %d %d\n", info->interval, info->output_type); /* Printf addresses */ fprintf(fd, "# %s %s\n", inet_ntoa(rec->ip_addr), ether_hwtoa((unsigned char *)rec->hw)); i = 0; while (qual != NULL && i <= qual->current-1) { /* write entry */ range_sec = qual->tstamp[i].tv_sec - start_time.tv_sec; if (info->output_type == 1) { /* timestamp, seconds */ fprintf(fd, "%lu %u\n", range_sec, qual->qual[i].qual); } else if (info->output_type == 2) { /* timestamp, dmsec, difference */ range_usec = qual->tstamp[i].tv_usec - start_time.tv_usec; if (range_usec < 0) { range_sec--; range_usec += 1000000; } range_dmsec = range_sec * 100 + range_usec/10000;#ifdef TEST if (i > 0) { diff = (qual->tstamp[i].tv_sec - qual->tstamp[i-1].tv_sec) * 1000000 - qual->tstamp[i-1].tv_usec + qual->tstamp[i].tv_usec; } fprintf(fd, "%lu.%lu %u (%lu)\n", range_sec, range_usec, qual->qual[i].qual, diff);#else fprintf(fd, "%lu %u\n", range_dmsec, qual->qual[i].qual);#endif } else if (info->output_type == 3) { /* timestamp, msec */ fprintf(fd, "%lu %u\n", qual->tstamp[i].tv_sec*1000+ qual->tstamp[i].tv_usec/1000 - (start_time.tv_sec*1000- start_time.tv_usec/1000), qual->qual[i].qual); } else if (info->output_type == 4) { /* timestamp, realtime, dmsec */ fprintf(fd, "%lu %u\n", qual->tstamp[i].tv_sec*100+ qual->tstamp[i].tv_usec/10000, qual->qual[i].qual); } else if (info->output_type == 0) { /* plain quality */ fprintf(fd, "%d", qual->qual[i].qual); } else { fprintf(stderr, "Unknown output type! (%d)\n", info->output_type); fclose(fd); return -1; } if (qual->current >= REC_NODE_CHUNK && i >= (qual->current-1) && qual->next != NULL) { qual = qual->next; i = 0; DEBUG(DEBUG_FLAG, "dump_fa: Next qual node\n"); } else i++; } if (info->output_type > 0 && range_sec > 0) { /* generate gnuplot header file */ snprintf(name, FILENAME_MAX, "FA-%s-dump.plot", inet_ntoa(rec->ip_addr)); header = fopen(name, "w"); if (!header) { DEBUG(DEBUG_FLAG, "dump_fa: fopen: %s\n", strerror(errno)); fclose(fd); return -1; } fprintf(header, "set output \"%s.gif\"\n", inet_ntoa(rec->ip_addr)); if (info->output_type == 1) fprintf(header, "set terminal gif small size %d,%d\n" "set xlabel \"Time t/s\"\n" "set ylabel \"Quality\"\n" "plot [0:%ld] [0:%d] 'FA-%s-dump.dat' title " "\"FA (%s)\" with lines lt 3 \n", IMG_X, IMG_Y, range_sec, Q_RANGE, inet_ntoa(rec->ip_addr), inet_ntoa(rec->ip_addr)); else if (info->output_type == 2) fprintf(header, "set terminal gif small size %d,%d\n" "set xlabel \"Time t/10msec\"\n" "set ylabel \"Quality\"\n" "plot [%ld:%ld] [0:%d] 'FA-%s-dump.dat' " "title \"FA (%s)\" with lines lt 3 \n", IMG_X, IMG_Y, start_time.tv_sec*100, start_time.tv_sec*100+range_sec*100, Q_RANGE, inet_ntoa(rec->ip_addr), inet_ntoa(rec->ip_addr)); else if (info->output_type == 3) fprintf(header, "set terminal gif small size %d,%d\n" "set xlabel \"Time t/ms\"\n" "set ylabel \"Quality\"\n" "plot [0:%ld] [0:%d] 'FA-%s-dump.dat' title " "\"FA (%s)\" with lines lt 3 \n", IMG_X, IMG_Y, range_sec*1000, Q_RANGE, inet_ntoa(rec->ip_addr), inet_ntoa(rec->ip_addr)); else if (info->output_type == 4) fprintf(header, "set terminal gif small size %d,%d\n" "set xlabel \"Time t/ms\"\n" "set ylabel \"Quality\"\n" "plot [%ld:%ld] [0:%d] 'FA-%s-dump.dat' title " "\"FA (%s)\" with lines lt 3 \n", IMG_X, IMG_Y, start_time.tv_sec*1000, start_time.tv_sec*1000+range_sec, Q_RANGE, inet_ntoa(rec->ip_addr), inet_ntoa(rec->ip_addr)); /* print entry into combined plot */ len = strlen(info->plot_str); if (len + 100 < PLOT_STR_SIZE) snprintf(&info->plot_str[len], 100, "'FA-%s-dump.dat' title \"FA %s\" " "with lines, ", inet_ntoa(rec->ip_addr), inet_ntoa(rec->ip_addr)); fclose(header); } fclose(fd); return 1;}int rec_dump(int type, int interval){ struct dump info; char name[FILENAME_MAX]; long range; int len; FILE *header; struct timeval stop_time; DEBUG(DEBUG_FLAG, "rec_dump\n"); /* dump the data in specified format (type) */ if (rec_hash == NULL) { DEBUG(DEBUG_FLAG, "rec_dump: hashtable NULL\n"); return -1; } memset(&info, 0, sizeof(info)); info.output_type = type; info.interval = interval; hashtable_iterator(rec_hash, dump_fa, &info); len = strlen(info.plot_str); if (len <= 0) { DEBUG(DEBUG_FLAG, "rec_dump: info plot string < 0\n"); return 0; } /* Make special group gnuplot file */ snprintf(name, FILENAME_MAX, "group.plot"); header = fopen(name, "w"); if (header == NULL) { DEBUG(DEBUG_FLAG, "rec_dump: fopen: %s\n", strerror(errno)); return -1; } gettimeofday(&stop_time, NULL); range = stop_time.tv_sec - start_time.tv_sec; fprintf(header, "set output \"group.gif\"\n"); if (type == 1) fprintf(header, "set terminal gif large size %d,%d\n" "set xlabel \"Time t/s\"\n" "set ylabel \"Quality\"\n" "plot [0:%ld] [0:%d] ", G_IMG_X, G_IMG_Y, range, Q_RANGE); else if (type == 2 || type == 4) fprintf(header, "set terminal gif large size %d,%d\n" "set xlabel \"Time t/10msec\"\n" "set ylabel \"Quality\"\n" "plot [0:%ld] [0:%d] ", G_IMG_X, G_IMG_Y, range*100, Q_RANGE); else if (type == 3) fprintf(header, "set terminal gif large size %d,%d\n" "set xlabel \"Time t/ms\"\n" "set ylabel \"Quality\"\n" "plot [0:%ld] [0:%d] ", G_IMG_X, G_IMG_Y, range*1000, Q_RANGE); info.plot_str[len - 2] = '\n'; info.plot_str[len - 1] = '\0'; fprintf(header, info.plot_str); if (fclose(header)) DEBUG(DEBUG_FLAG, "rec_dump: fclose: %s\n", strerror(errno)); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -