iwspy-gather.c

Go to the documentation of this file.
00001 /* $Id: iwspy-gather.c,v 1.13 2001/08/16 14:15:38 jm Exp $
00002  * Dynamics iwspy quality statistics collector module
00003  *
00004  * Dynamic hierarchial IP tunnel
00005  * Copyright (C) 1998-2001, Dynamics group
00006  *
00007  * This program is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License version 2 as
00009  * published by the Free Software Foundation. See README and COPYING for
00010  * more details.
00011  */
00012 
00013 #include <stdio.h>
00014 #include <malloc.h>
00015 #include <unistd.h>
00016 #include <stdlib.h>
00017 #include <string.h>
00018 #include <getopt.h>
00019 #include <signal.h>
00020 #include <errno.h>
00021 #include <asm/types.h>
00022 #include <sys/types.h>
00023 #include <sys/socket.h>
00024 #include <sys/ioctl.h>
00025 #include <sys/time.h>
00026 #include <linux/wireless.h>
00027 #include "owntypes.h"
00028 #include <linux/filter.h>
00029 #include <netinet/ip_icmp.h>
00030 #include <netinet/ip.h>
00031 #include <features.h>    /* for the glibc version number */
00032 
00033 #if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
00034 #include <netpacket/packet.h>
00035 #include <net/ethernet.h>     /* the L2 protocols */
00036 #include <netinet/if_ether.h>
00037 #else
00038 #include <linux/if_packet.h>
00039 #include <linux/if_ether.h>   /* The L2 protocols */
00040 #endif
00041 
00042 #include "debug.h"
00043 #include "agentadv.h"
00044 #include "dyn_wireless.h"
00045 #include "monitor.h"
00046 #include "fixed_fd_zero.h"
00047 #include "util.h"
00048 #include "dyn_iwspy_rec.h"
00049 
00050 #define DEBUG_FLAG '5'
00051 #define TIME_ERROR 10000
00052 #define DEFAULT_INTERVAL 1000000 /* in usecs */
00053 #define USAGE "iwspy_gather [-h] [-v] -d <device_name> [-i <msecs>] [-l <seconds>]\n"\
00054 "Options:\n"\
00055 "\t-h\t\t\thelp (--help)\n"\
00056 "\t-v\t\t\tverbose (--verbose)\n"\
00057 "\t-d <name>\t\tdevice (--device)\n"\
00058 "\t-i <milliseconds>\tchecking interval in milliseconds (--interval)\n"\
00059 "\t-l <seconds>\t\tmonitoring length in seconds (--length)\n"
00060 
00061 extern int opt_debug;
00062 
00063 static struct option const long_options[] =
00064 {
00065         {"interval", required_argument, NULL, 'i'},
00066         {"interactive", no_argument, NULL, 'a'},
00067         {"help", no_argument, NULL, 'h'},
00068         {"device", required_argument, NULL, 'd'},
00069         {"length", required_argument, NULL, 'l'},
00070         {"verbose", no_argument, NULL, 'v'},
00071         {0, 0, 0, 0}
00072 };
00073 
00074 int iwspy_sock, bcast_sock, adver_sock, interval;
00075 char ifname[IFNAMSIZ];
00076 char cache[ETH_ALEN*IW_MAX_SPY+1];
00077 
00078 
00079 static int add_check_mark(struct timeval *tstamp)
00080 {
00081         char buffer[(sizeof(struct iw_quality) +
00082                      sizeof(struct sockaddr)) *
00083                    (IW_MAX_SPY+1)];
00084         int monitored, i;
00085         struct sockaddr *hws;
00086         struct iw_quality *qual;
00087 
00088         monitored = dyn_wireless_iwspy_get(iwspy_sock, ifname, buffer);
00089         if (monitored < 0) {
00090                 fprintf(stderr, "add_check_mark: get iwspy failed\n");
00091                 return 1;
00092         }
00093         hws = (struct sockaddr *)buffer;
00094         qual = (struct iw_quality *)
00095                 (buffer + (sizeof(struct sockaddr) * monitored));
00096         
00097         for (i = 0 ; i < monitored; i++) {
00098                 if (qual[i].updated) {
00099                         if (rec_add_qual(hws[i].sa_data, &qual[i], tstamp))
00100                                 fprintf(stderr, "add_check_mark: rec_add_qual "
00101                                         "failed\n");
00102                 } else 
00103                         DEBUG(DEBUG_FLAG, "add_check_mark: monitored entry "
00104                               "not updated (%d)\n", i);
00105         }
00106 
00107         return 0;       
00108 }
00109 
00110 
00111 static int check_monitored(unsigned char *hw, struct in_addr addr)
00112 {
00113         char buffer[(sizeof(struct iw_quality) +
00114                      sizeof(struct sockaddr)) *
00115                    (IW_MAX_SPY+1)];
00116         static int in_cache = 0;
00117         int i, monitored;
00118         struct sockaddr *hws;
00119         struct iw_quality *qual;
00120         struct timeval t;
00121 
00122 
00123         /* already monitored? */
00124         for (i = 0 ; i < in_cache; i++)
00125                 if(!(memcmp(&cache[i*ETH_ALEN], hw, ETH_ALEN)))
00126                         return 0;
00127 
00128         monitored = dyn_wireless_iwspy_get(iwspy_sock, ifname, buffer);
00129         if (monitored < 0) {
00130                 fprintf(stderr, "get_iwspy failed\n");
00131                 return -1;
00132         }
00133         hws = (struct sockaddr *)buffer;
00134         qual = (struct iw_quality *)
00135                 (buffer + (sizeof(struct sockaddr) * monitored));
00136 
00137         DEBUG(DEBUG_FLAG, "check_monitored: monitored = %d\n", monitored);
00138         if (monitored >= MAX_MONITOR)
00139                 return 1;
00140         
00141         memcpy(hws[monitored].sa_data, hw, ETH_ALEN);
00142         monitored++;
00143         if (dyn_wireless_iwspy_set(iwspy_sock, ifname, buffer, 
00144                                    monitored) < 0) {
00145                 fprintf(stderr, "set_iwspy failed!\n");
00146                 return -1;
00147         } else {
00148                 gettimeofday(&t, NULL);
00149                 rec_add_long(hws, hw, addr, qual, &t, monitored);
00150         }
00151         memcpy(&cache[in_cache*ETH_ALEN], hw, ETH_ALEN);
00152         in_cache++;
00153 
00154         return 0;
00155 }
00156 
00157 
00158 #define MAX_ADV_RADDRS 10
00159 #define MAX_ADV_COADDRS 10
00160 static int collect_stats(unsigned long const ival, long const length)
00161 {
00162         char buf[MAX_ADV_MSG];
00163         struct adv_extensions adv;
00164         fd_set rfds;
00165         struct in_addr ip_addr;
00166         struct timeval last_sol, tv;
00167         int current, retval = 0;
00168         static int monitoring = 0;
00169         unsigned long passed, diff = 0;
00170 
00171 
00172         FD_ZERO(&rfds);
00173         gettimeofday(&last_sol, NULL);
00174         current = 0;
00175         DEBUG(DEBUG_FLAG, "interval = %lu\n", ival);
00176 
00177         for (;;) {
00178                 gettimeofday(&tv, NULL);
00179                 passed = usec_passed(&last_sol, &tv);
00180                 if (length > 0 && tv.tv_sec > length) 
00181                         return 0;
00182 
00183                 if (passed >= (ival - TIME_ERROR) ) {
00184                         /* check mark */
00185                         add_check_mark(&tv);
00186                 }
00187 
00188                 if (retval > 0 && FD_ISSET(adver_sock, &rfds)) {
00189                         if (handle_icmp_adv(adver_sock, buf, MAX_ADV_MSG,
00190                                             &adv) == 1) {
00191                                 ip_addr.s_addr = adv.ip->saddr;
00192                                 monitoring =
00193                                         check_monitored(adv.from.sll_addr,
00194                                                         ip_addr);
00195                         } else {
00196                                 fprintf(stderr, "handle_icmp_adv failed\n");
00197                         }
00198                 }
00199 
00200                 if (passed >= (ival - TIME_ERROR) ) {
00201                         /* send agent solicitation */
00202                         if (send_agent_solicitation(bcast_sock) < 0)
00203                                 fprintf(stderr, "send_agent_solicitation "
00204                                         "failed!\n");
00205                         else {
00206                                 gettimeofday(&last_sol, NULL);
00207                                 diff = usec_passed(&tv, &last_sol);
00208                         }
00209                         if (ival - diff > 0)
00210                                 set_usecs(&tv, ival - diff);
00211                         else
00212                                 continue;
00213                 } else {
00214                         if (ival - passed > 0)
00215                                 set_usecs(&tv, ival - passed);
00216                         else
00217                                 continue;
00218 /*                      DEBUG(DEBUG_FLAG, "increase time value (diff %lu, "
00219                                 "wait %lu)\n", ival-passed, 
00220                                 tv.tv_sec * 1000000+tv.tv_usec); */
00221                 }
00222 
00223                 FD_ZERO(&rfds);
00224                 if (!monitoring)
00225                         FD_SET(adver_sock, &rfds);
00226                 /* sleep */
00227                 retval = select(FD_SETSIZE, &rfds, NULL, NULL, &tv);
00228         }
00229 
00230         return -1; /* never reached */
00231 }
00232 
00233 
00234 static void clean_up(int signal)
00235 {
00236         /* Make data files */
00237         rec_dump(3, interval);
00238         rec_clean_up();
00239         /* remove monitored entries from kernel */
00240         dyn_wireless_iwspy_set(iwspy_sock, ifname, NULL, 0);
00241         close(iwspy_sock);
00242         close(bcast_sock);
00243         close(adver_sock);
00244         exit(0);
00245 }
00246 
00247 
00248 static int init_sockets(void)
00249 {
00250         __u32 filter = 0;
00251 
00252         filter = ICMP_FILTER_MN;
00253         iwspy_sock = dyn_wireless_create_socket();
00254         bcast_sock = open_agent_icmp_socket(ifname, filter);
00255         adver_sock = open_agent_icmp_adv_socket(ifname, AGENTADV_FILTER_ADV);
00256 
00257         if (iwspy_sock < 0 || bcast_sock < 0 || adver_sock < 0)
00258                 return 1;
00259         return 0;
00260 }
00261 
00262 
00263 int main(int argc, char **argv)
00264 {
00265         unsigned long length = 0;
00266         int ret = -1, c, oindex;
00267         struct timeval end;
00268 
00269         interval = -1;
00270 
00271         if (fopen("/var/run/dynamics_mn_read", "r") != NULL ||
00272             fopen("/var/run/dynamics_mn_admin", "r") != NULL) {
00273                 fprintf(stderr, "Don't run Mobile Node and iwspy_gather "
00274                         "together. Exiting..\n");
00275                 return 1;
00276         }
00277           
00278         /* parse arguments */
00279         while ((c = getopt_long(argc, argv, "i:d:hl:v", long_options, 
00280                                 &oindex)) 
00281                != EOF) {
00282                 switch (c) {
00283                 case 'i': /* interval */
00284                         DEBUG(DEBUG_FLAG, "option i (Interval) with value"
00285                               " '%s'\n", optarg);
00286                         interval = atoi(optarg);
00287                         break;
00288                 case 'd': /* device */
00289                         DEBUG(DEBUG_FLAG, "option d (Device) with value"
00290                               " '%s'\n", optarg);
00291                         ret = dyn_wireless_get_ifname(optarg, ifname);
00292                         break;
00293                 case 'l': /* stop after <arg> seconds */
00294                         DEBUG(DEBUG_FLAG, "option l (Length) with value"
00295                               " '%s'\n", optarg);
00296                         length = atol(optarg);
00297                         if (length <= 0) {
00298                                 fprintf(stderr, "length must be >0!\n");
00299                                 return 1;
00300                         }
00301                         gettimeofday(&end, NULL);
00302                         length += end.tv_sec;
00303                         break;
00304                 case 'v': /* verbose */
00305                         opt_debug = 1;
00306                         break;
00307                 case 'h': /* Usage */
00308                 default:
00309                         printf(USAGE);
00310                         return 1;
00311                 }
00312         }
00313 
00314         /* interface given? */
00315         if (ret < 0) {
00316                 fprintf(stderr, "No device argument!\n");
00317                 printf(USAGE);
00318                 return 1;
00319         } 
00320 
00321         /* decent range? */
00322         if (interval >= 0 && interval < 10) {
00323                 fprintf(stderr, "Interval must be at least 10 msecs\n");
00324                 return 2;
00325         }
00326 
00327         /* open sockets */
00328         if (init_sockets()) {
00329                 fprintf(stderr, "Open socket(s) failed\n");
00330                 return 3;
00331         }
00332 
00333         /* Setup signal handler */
00334         signal(SIGTERM, clean_up);
00335         signal(SIGINT, clean_up);
00336         signal(SIGHUP, clean_up);
00337 
00338         /* initialize quality recorder database */
00339         if (rec_init() < 0) {
00340                 fprintf(stderr, "Recorder initialization failed!\n");
00341                 return 4;
00342         }
00343 
00344         /* clear cache */
00345         memset(cache, 0, sizeof(cache));
00346 
00347         /* begin harvesting */
00348         if (interval < 0)
00349                 collect_stats(DEFAULT_INTERVAL, length);
00350         else
00351                 collect_stats((unsigned long)(interval*1000), length);
00352 
00353         clean_up(0);
00354         return 0;
00355 }

Generated on Tue Jan 15 08:50:43 2008 for Virtual foreign agent generator version 0.1 by  doxygen 1.5.1