iwspy-sim.c

Go to the documentation of this file.
00001 /* $Id: iwspy-sim.c,v 1.12 2001/07/11 15:12:44 jm Exp $
00002  * Dynamics iwspy simulator module
00003  *
00004  * Dynamic hierarchial IP tunnel
00005  * Copyright (C) 1998-2000, 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 
00014 #include <malloc.h>
00015 #include <unistd.h>
00016 #include <stdio.h>
00017 #include <getopt.h>
00018 extern char *optarg;
00019 extern int optind, opterr, optopt;
00020 #include <errno.h>
00021 #include <string.h>
00022 #include <assert.h>
00023 #include <limits.h>
00024 #include <asm/types.h>
00025 #include <sys/types.h>
00026 #include <sys/socket.h>
00027 #include <sys/ioctl.h>
00028 #include <linux/wireless.h>
00029 
00030 #include "dyn_wireless.h"
00031 #include "debug.h"
00032 #include "util.h"
00033 
00034 #define DEBUG_FLAG '4'
00035 
00036 #define USAGE "iwspy_sim -d <device> [-h] {[<mac_address> "\
00037 "<qualities_file>] .. | -m <mac_address>}\n"
00038 #define MAX_LINE 80
00039 #define MAX_FILES 64
00040 
00041 extern int opt_debug;
00042 
00043 static struct option const long_options[] =
00044 {
00045         {"help", no_argument, NULL, 'h'},
00046         {"device", required_argument, NULL, 'd'},
00047         {0, 0, 0, 0}
00048 };
00049 
00050 int free_nodes(struct quality_values *q)
00051 {
00052         struct quality_values *t;
00053 
00054         while (q != NULL) {
00055                 t = q;
00056                 q = q->next;
00057                 free(t);
00058         }
00059 
00060         return 0;
00061 }
00062 
00063 /* Format of file (filetype):
00064      0 = no timestamp, only quality value in one line
00065      1 = timstamps in seconds and quality value in one line
00066      2 = timestamps in tens of milliseconds and qual. value in one line
00067 */
00068 struct quality_values *read_quals(FILE *f, int *ival, int *filetype)
00069 {
00070         struct quality_values *q, *t;
00071         char buf[MAX_LINE], hw[ETH_ALEN+1], addr[20];
00072         int ret, qual;
00073         unsigned long tstamp;
00074         
00075 
00076         q = t = dyn_wireless_get_quals_node(NULL);
00077 
00078         /* Read the interval from the first line */
00079         *ival = 0;
00080         fgets(buf, MAX_LINE, f);
00081         ret = sscanf(buf, "# %d %d", ival, filetype);
00082         if (ret != 2) {
00083                 fprintf(stderr, "Header not found! ´# <ival(in msec)> "
00084                         "<filetype (0:no timestamps, 1:timestamps in seconds"
00085                         ", 2:timestamps in tens of milli seconds>'. "
00086                         "buf: '%s'\n", buf);
00087                 return NULL;
00088         }
00089         fgets(buf, MAX_LINE, f);
00090         ret = sscanf(buf, "# %19s %6s", addr, hw);
00091         if (ret != 2) {
00092                 fprintf(stderr, "Addresses not found. Should be: "
00093                         "'# <ip-addr> <hw-addr>'. buf: '%s'\n", buf);
00094                 return NULL;
00095         }
00096         /* Read values into structure */
00097         while (fgets(buf, MAX_LINE, f)) {
00098                 if (*filetype == 0) /* no timestamps */
00099                         sscanf(buf, "%d", &qual);
00100                 /* timestamps in seconds OR in milliseconds/10 */
00101                 else if (*filetype == 1 || *filetype == 2 || *filetype == 3) 
00102                         sscanf(buf, "%lu %d", &tstamp, &qual);
00103                 else {
00104                         fprintf(stderr, "Unknown filetype! (%d)\n", *filetype);
00105                         return NULL;
00106                 }
00107                 if (qual < 0 || qual > 100) { /* FIX: Exact range */
00108                         fprintf(stderr, "Invalid quality value! (%lu) "
00109                                 "(%d) '%s'\n", 
00110                                 tstamp, qual, buf);
00111                         return NULL;
00112                 }
00113                 if (t->num_of_quals >= MAX_NUM_QUALS)
00114                         t = dyn_wireless_get_quals_node(t);
00115                 /* store value */
00116                 t->sim_quals[t->num_of_quals] = qual;
00117                 t->sim_timestamps[t->num_of_quals] = tstamp;
00118                 t->num_of_quals++;
00119         }
00120 
00121         return q;
00122 }
00123 
00124 FILE *get_file(char *name)
00125 {
00126         FILE *fd;
00127 
00128         fd = fopen(name, "r");
00129         if (fd)
00130                 return fd;
00131         fprintf(stderr, "get_file - %s: %s\n", name, strerror(errno));
00132 
00133         return NULL;    
00134 }
00135 
00136 int close_file(FILE *f)
00137 {
00138         fclose(f);
00139         return 0;
00140 }
00141 
00142 int parse_hw_address(char *string, char *hw)
00143 {
00144         int ret;
00145 
00146         ret = sscanf(string, "%02x:%02x:%02x:%02x:%02x:%02x", 
00147                      (unsigned int *)&hw[0], (unsigned int *)&hw[1], 
00148                      (unsigned int *)&hw[2], (unsigned int *)&hw[3], 
00149                      (unsigned int *)&hw[4], (unsigned int *)&hw[5]);
00150         if (ret == 6)
00151                 return 1; /* TRUE */
00152         
00153         return 0; /* FALSE */
00154 }
00155 
00156 void print_quals(struct quality_values *q)
00157 {
00158         unsigned long i, j; 
00159 
00160         j = 0;
00161         while (q != NULL) {
00162                 for (i = 0; i < q->num_of_quals; i++)
00163                         if (q->sim_timestamps[i] > 0)
00164                                 printf("%-4lu %3d\n", q->sim_timestamps[i], 
00165                                        q->sim_quals[i]);
00166                         else
00167                                 printf("%-4ld %3d\n", i + j, q->sim_quals[i]);
00168                 j += q->num_of_quals;
00169                 q = q->next;
00170         }
00171 }
00172 
00173 int parse_pairs(int oindex, int const argc, char **argv, char *hw, 
00174                 FILE *qfile[], int *qfile_index) 
00175 {
00176         int ret;
00177 
00178         *qfile_index = 0;
00179         while (oindex < argc-1) {
00180                 printf("oindex = %d, argc = %d, qfile_index = %d\n", 
00181                        oindex, argc, *qfile_index );
00182                 ret = parse_hw_address(argv[oindex], 
00183                                        &hw[(*qfile_index)*ETH_ALEN]);
00184                 if (!ret) {
00185                         fprintf(stderr, "Couldn't parse hw address!\n");
00186                         printf(USAGE);
00187                         return 1;
00188                 }
00189                 qfile[*qfile_index] = get_file(argv[oindex+1]);
00190                 if (qfile[*qfile_index] == NULL)
00191                         return 1;
00192                 (*qfile_index)++;
00193                 if (*qfile_index >= MAX_FILES)
00194                         return 2;
00195                 oindex += 2;
00196         }
00197 
00198         return 0;
00199 }
00200 
00201 static int feed_quality_values(int sock, char *ifname, char *hw, 
00202                                FILE *qfile[], int qfile_index)
00203 {
00204         struct quality_values *quals[MAX_FILES];
00205         int ivals[MAX_FILES], filetype[MAX_FILES], min_ival = INT_MAX;
00206         int nodes_left = 1, i, ret, r; 
00207 
00208         /* read values from the file(s) */
00209         DEBUG(DEBUG_FLAG, "feed_quality_values (%d)\n", qfile_index);
00210         for (i = 0; i < qfile_index; i++) {
00211                 assert(qfile[i] != NULL);
00212                 quals[i] = read_quals(qfile[i], &ivals[i], &filetype[i]);
00213                 if (quals[i] == NULL) {
00214                         DEBUG(DEBUG_FLAG, "Reading quals failed! (%d)\n",
00215                               qfile_index);
00216                 }
00217                 if (ivals[i] < min_ival) 
00218                         min_ival = ivals[i];
00219         }
00220 
00221         DEBUG(DEBUG_FLAG, "min_ival = %d, MAX_NUM_QUALS = %d\n", 
00222               min_ival, MAX_NUM_QUALS);
00223         while (nodes_left) {
00224                 nodes_left = 0;
00225                 for (i = 0; i < qfile_index; i++) {
00226                         if (quals[i] == NULL) /* no buffered quality 
00227                                                  values left for this hw */
00228                                 continue;
00229                         ret = dyn_wireless_check_simulator(sock, ifname, 
00230                                                            &hw[i*ETH_ALEN]);
00231                         if (ret == 3) {
00232                                 DEBUG(DEBUG_FLAG, "Feeding new chunk (%s)\n",
00233                                       ether_hwtoa((unsigned char *)
00234                                                   &hw[i*ETH_ALEN]));
00235                                 r = dyn_wireless_set_simulator(sock, ifname, 
00236                                                                &hw[i*ETH_ALEN],
00237                                                                quals[i], 
00238                                                                ivals[i], 
00239                                                                filetype[i]);
00240                                 if (r)
00241                                         return r;
00242                                 quals[i] = quals[i]->next;
00243                                 if (quals[i] != NULL)
00244                                         nodes_left = 1;
00245                         } else if (ret == 2) {
00246 /*                              DEBUG(DEBUG_FLAG, "No room for new chunk "
00247                                       "(%s)\n", ether_hwtoa((unsigned char *)
00248                                       &hw[i*ETH_ALEN]));*/
00249                                 if (quals[i]->next != NULL)
00250                                         nodes_left = 1;
00251                         } else if (ret == 1) {
00252                                 DEBUG(DEBUG_FLAG, "Entry not found (%s)\n",
00253                                       ether_hwtoa((unsigned char *)
00254                                                   &hw[i*ETH_ALEN]));
00255                         } else {
00256                                 DEBUG(DEBUG_FLAG, "check_quals returned %d\n",
00257                                       ret);
00258                         }
00259 
00260                                 
00261                 }
00262                 /* check every 100 msec */
00263                 if (nodes_left)
00264                         usleep(100000); 
00265         }
00266 
00267         for (i = 0; i < qfile_index; i++) {
00268                 free_nodes(quals[i]);
00269         }
00270 
00271         return 0;
00272 }
00273 
00274 /* Use iwspy(8) to see monitored entries. Simulator can't be attached
00275  * to non existing iwspy entry in the kernel. The simulator (if
00276  * attached to the entry) just bypasses the real quality value and
00277  * reports the quality value from the attached quality vector
00278  * (SET_SIMULATOR). NOTICE: Whenever set-iwspy (SIOCSIWSPY) is used,
00279  * the simulator has to be reinitialized. This is because the
00280  * set-iwspy ioctl reinitialize all the entries in the kernel.
00281  * 
00282  * USAGE:
00283  *    iwspy-sim -m <mac_address> -d <device> [-f <qualities_file>]
00284  *
00285  * If <qualities_file> is given, SET_SIMULATOR is assumed, 
00286  * otherwise GET_SIMULATOR.  
00287  */
00288 int main(int argc, char **argv)
00289 {
00290         int oindex = 0, ret = 1, ret2 = 0;
00291         char hw[MAX_FILES*ETH_ALEN];
00292         char get_hw[ETH_ALEN];
00293         FILE *qfile[MAX_FILES];
00294         int qfile_index = 0;
00295         struct quality_values *quals = NULL;
00296         char ifname[IFNAMSIZ+1];
00297         signed char c;
00298         int sock, i;
00299                 
00300         memset(qfile, 0, sizeof(qfile));
00301         while ((c = getopt_long(argc, argv, "+d:hm:v", long_options, &oindex)) 
00302                != EOF) {
00303                 switch (c) {
00304                 case 'd':
00305                         DEBUG(DEBUG_FLAG, "option d (Device) with value "
00306                               "'%s'\n", optarg);
00307                         ret = dyn_wireless_get_ifname(optarg, ifname);
00308                         break;
00309                 case 'm':
00310                         DEBUG(DEBUG_FLAG, "option m (Mac address) with value "
00311                               "'%s'\n", optarg);
00312                         ret2 = parse_hw_address(optarg, get_hw);
00313                         break;
00314                 case 'h':
00315                         printf(USAGE);
00316                         return 0;
00317                         break;
00318                 case 'v':
00319                         opt_debug = 1;
00320                         break;
00321                 default:
00322                         fprintf(stderr, "Unknown option %c\n", c);
00323                         printf(USAGE);
00324                         break;
00325                 }
00326         }
00327         
00328                 
00329         if (ret) {
00330                 printf("Couldn't parse device name!\n");
00331                 printf(USAGE);
00332                 return 1;
00333         }
00334 
00335 
00336         /* initialize socket */
00337         sock = dyn_wireless_create_socket();
00338         if (sock < 0) {
00339                 fprintf(stderr, "Socket creation failed (%s)\n",
00340                         strerror(errno));
00341                 return 1;
00342         }
00343 
00344         if (ret2) {
00345                 /* GET_SIMULATOR */
00346                 DEBUG(DEBUG_FLAG, "GET\n");
00347                 quals = dyn_wireless_get_simulator(sock, ifname, get_hw);
00348                 print_quals(quals);
00349                 free_nodes(quals);
00350         } else {
00351                 /* SET_SIMULATOR */
00352                 /* parse hw address and qualities file pairs */
00353                 DEBUG(DEBUG_FLAG, "SET\n");
00354                 if (parse_pairs(optind, argc, argv, hw, qfile, &qfile_index)) {
00355                         fprintf(stderr, "Command line parsing failed!\n");
00356                         return 1;
00357                 }
00358                 feed_quality_values(sock, ifname, hw, qfile, qfile_index);
00359         }
00360 
00361         for (i = 0; qfile[i] != NULL; i++)
00362                 close_file(qfile[i]);
00363         return 0;
00364 }

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