monitor.c

Go to the documentation of this file.
00001 /* $Id: monitor.c,v 1.83 2001/09/29 16:06:39 jm Exp $
00002  * Monitor 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 /*
00014   ---------------
00015   Main call graph
00016   ---------------
00017 
00018 
00019             MONITOR_register_module 
00020                     handler_register 
00021             MONITOR_unregister_module 
00022                     dyn_wireless_iwspy_set 
00023  r                  rec_dump 
00024  r                  rec_clean_up 
00025             
00026 
00027   "event_FA" handlers       
00028   จจจจจจจจจจจจจจจจจจจ
00029 
00030             monitor_add_fa 
00031                     gettimeofday 
00032                     monitor 
00033                             dyn_wireless_iwspy_get 
00034                             update_statistics 
00035  r                          rec_init 
00036  r                          rec_add_long 
00037                             get_qual_avg
00038  r                          rec_dump 
00039  r                          rec_clean_up 
00040                             get_free_slot 
00041                             dyn_wireless_iwspy_set 
00042             monitor_del_fa 
00043                     demonitor 
00044                             dyn_wireless_iwspy_get 
00045                             dyn_wireless_iwspy_set 
00046             monitor_get_fa 
00047                     mark_new_entries 
00048                     test_newest_fa_policy 
00049                     prioritize_all 
00050                     monitor_balance_prio 
00051 
00052             
00053   "event_INTERFACE" handlers
00054   จจจจจจจจจจจจจจจจจจจจจจจจจจ
00055             
00056             monitor_interface_down 
00057                     monitor_dev_down 
00058                             dyn_wireless_iwspy_set 
00059                     handler_unregister 
00060             monitor_interface_up 
00061                     monitor_dev_up 
00062                             dyn_wireless_create_socket 
00063                             dyn_wireless_iwspy_get 
00064                             dyn_wireless_iwspy_set 
00065                             dyn_wireless_get_channel 
00066                             dyn_wireless_set_channel 
00067                             dyn_wireless_get_range 
00068                     handler_register 
00069  r                  rec_init 
00070  r                  rec_dump 
00071  r                  rec_clean_up 
00072             
00073  r = Quality Recorder
00074 
00075 */
00076 
00077 #include <sys/types.h>
00078 #include <sys/socket.h>
00079 #include <sys/ioctl.h>
00080 #include <sys/time.h>
00081 #include <netinet/ip_icmp.h>
00082 #include <netinet/in.h>
00083 #include <arpa/inet.h>
00084 #include <asm/types.h>
00085 #include <stdio.h>
00086 #include <stddef.h>
00087 #include <errno.h>
00088 #include <fcntl.h>
00089 #include <ctype.h>
00090 #include <stdlib.h>
00091 #include <string.h>
00092 #include <unistd.h>
00093 #include <syslog.h>
00094 #include <assert.h>
00095 
00096 #include <unistd.h>
00097 #include <features.h>    /* for the glibc version number */
00098 #if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
00099 #include <netpacket/packet.h>
00100 #include <net/ethernet.h>     /* the L2 protocols */
00101 #include <netinet/if_ether.h>
00102 #else
00103 #include <linux/if_packet.h>
00104 #include <linux/if_ether.h>   /* The L2 protocols */
00105 #endif
00106 #include "owntypes.h"
00107 #include <linux/filter.h>
00108 
00109 #include "mn.h"
00110 #include "monitor.h"
00111 #include "debug.h"
00112 #include "util.h"
00113 #include "mn_agentadv.h"
00114 #include "mn_handler.h"
00115 #include "list.h"
00116 #include "dyn_wireless.h"
00117 #include "dyn_iwspy_rec.h"
00118 
00119 #ifndef TRUE
00120 #define TRUE 1
00121 #endif
00122 
00123 #ifndef FALSE
00124 #define FALSE 0
00125 #endif
00126 
00127 #define DEBUG_FLAG 'm'
00128 #define REC_DUMP_TYPE 4
00129 
00130 /**************/
00132 /**************/
00133 
00134 /* event_INTERFACE handlers: */
00135 static int monitor_interface_up(void *data);
00136 static int monitor_interface_down(void *data);
00137 /* event_FA handlers: */
00138 static int monitor_get_fa(void *data);
00139 static int monitor_add_fa(void *data);
00140 static int monitor_del_fa(void *data);
00141 
00144 struct monitor_global_data mon_conf;
00145 struct monitor_interface mon_devs[MAX_INTERFACES];
00146 int mon_rec_qual_initialized;
00147 
00148 /****************/
00150 /****************/
00151 
00152 /* configuration variables. These are listed and modified with 
00153  * dynmn_tool (monitor)
00154  */
00155 struct monitor_conf_vars monitor_conf[] = {
00156         {"Threshold (0-100)      ", 1, &mon_conf.threshold,      0, 100}, 
00157         {"Min-balance (0-100)    ", 1, &mon_conf.min_balance,    0, 100},
00158         {"Expirepercent (1-300)  ", 1, &mon_conf.expiretime,     1, 300},
00159         {"Old-FA-factor (0-100)  ", 1, &mon_conf.old_fa_factor,  0, 100},
00160         {"Worst-min-time (0- )   ", 8, &mon_conf.worst_min_time, 0,  -1},
00161         {"Worst-max-time (0- )   ", 8, &mon_conf.worst_max_time, 0,  -1},
00162         {"Average-length (1-10)  ", 1, &mon_conf.average_length, 1,  10},
00163         {"Default-channel (1-14) ", 1, &mon_conf.default_ch,     1,  14},
00164         {"Record-quality (0, 1)  ", 1, &mon_conf.rec_qual,       0,   1},
00165         {"SQ-cache (0, 1)        ", 1, &mon_conf.SQ_cache,       0,   1},
00166         {"", 0, NULL, 0, 0}
00167 };
00168 
00169 
00170 /***************/
00172 /***************/
00173 
00174 /*
00175  * Update signal quality vectors (FIFO), averages and
00176  * timestamps. Signal quality averages are stored in percent values
00177  * (avg: 0 - 100%)
00178  *
00179  * returns nothing 
00180  */
00181 static void update_statistics(struct sockaddr *hwa, struct iw_quality *qual,
00182                               struct timeval tstamp,
00183                               struct monitor_interface *dev, int monitored)
00184 {
00185         unsigned int j, k, i = 0, sum, p;
00186 
00187         /* every entry in the kernel structure */
00188         for (i = 0; i < monitored; i++) {
00189                 /* If quality updated */
00190                 if (!(qual[i].updated & 0x7))
00191                         continue;
00192                 /* find the correct entry from monitor structure */
00193                 for (j = 0; j < MAX_MONITOR; j++) {
00194                         if (dev->mon[j].active != 1 ||
00195                              (memcmp(hwa[i].sa_data, 
00196                                      dev->mon[j].adv->adv.from.sll_addr,
00197                                      ETH_ALEN)))
00198                                 continue;
00199 
00200                         /* update the FIFO pointer */
00201                         p = next(dev->mon[j].q10_index);
00202                         dev->mon[j].q10_index = p;
00203 
00204                         dev->mon[j].qual.level   = qual[i].level;
00205                         dev->mon[j].qual.qual    = qual[i].qual;
00206                         dev->mon[j].qual.noise   = qual[i].noise;
00207                         dev->mon[j].qual.updated = qual[i].updated;
00208 
00209                         /* history size is 10 */
00210                         /* (Bug in driver (>92)) */
00211                         if (dev->mon[j].qual.qual > dev->range.max_qual.qual)
00212                                 dev->mon[j].q10[p] = 
00213                                         dev->mon[j].q10[prev(p)];
00214                         else
00215                                 dev->mon[j].q10[p] = 
00216                                         dev->mon[j].qual.qual;
00217 
00218                         /* timestamps */
00219                         dev->mon[j].updated.tv_sec  = tstamp.tv_sec;
00220                         dev->mon[j].updated.tv_usec = tstamp.tv_usec;
00221 
00222                         if (monitor_check_policy(EAGER_SWITCH_BIT)) {
00223                                 dev->mon[j].avg  = ((100*dev->mon[j].q10[p])/
00224                                                     dev->range.max_qual.qual);
00225                                 return;
00226                         } 
00227                         
00228                         /* calculate the average. The number of
00229                            quality values used in the average
00230                            calculation is a configurable variable */
00231                         /* New entry doesn't have history */
00232 
00233                         if (mon_conf.average_length <= 0 || 
00234                             mon_conf.average_length > 10) {
00235                                 DEBUG(DEBUG_FLAG, "update_statistics: "
00236                                       "configuration variable: "
00237                                       "average_length was out of range! "
00238                                       " (%d)\n", mon_conf.average_length);
00239                                 mon_conf.average_length = DEFAULT_AVG_LEN;
00240                         }
00241 
00242                         sum = dev->mon[j].q10[p];
00243                         for (k = 1; k < mon_conf.average_length; k++) {
00244                                 /* new entries don't have history */
00245                                 if (dev->mon[j].q10[prev(p)] >= 255) {
00246                                         dev->mon[j].q10[prev(p)] =
00247                                                 dev->mon[j].q10[p];
00248                                 }
00249                                 sum += dev->mon[j].q10[prev(p)];
00250                                 p = prev(p);
00251                         }
00252 
00253                         /* calculate the average and normalize the result */
00254                         dev->mon[j].avg  = (unsigned short)
00255                                 ((sum*100/mon_conf.average_length)/
00256                                  dev->range.max_qual.qual);
00257                 }
00258         }
00259 }
00260 
00261 static int get_qual_avg(struct monitor_interface *dev, unsigned char *hw)
00262 {
00263         int j;
00264 
00265         for (j = 0; j < MAX_MONITOR; j++) {
00266                 if (dev->mon[j].active != 1 ||
00267                     (memcmp(hw, dev->mon[j].adv->adv.from.sll_addr, ETH_ALEN)))
00268                         continue;
00269                 /* entry found */
00270                 return dev->mon[j].avg;
00271         }
00272 
00273         DEBUG(DEBUG_FLAG, "get_qual_avg: mac not found!\n");
00274         return -1;
00275 }
00276 
00277 /*
00278  * Start monitoring NODE
00279  * 
00280  * Parameters: 
00281  *   dev       Interface structure
00282  *   adv       agentadv data
00283  *   tstamp    Timestamp
00284  *
00285  * returns:
00286  *     0       success
00287  *    -1       get iwspy or set iwspy failed
00288  *    -2       slots are full and the worst entry is current FA
00289  *    -3       already monitoring (usual case, not failure)
00290  */
00291 static int monitor(struct monitor_interface *dev, struct agentadv_data *adv, 
00292                    struct timeval tstamp)
00293 {
00294         int i, ph = -1, monitored, ret;
00295         struct sockaddr *hw;
00296         struct iw_quality *qual;
00297         char buffer[(sizeof(struct iw_quality) +
00298                      sizeof(struct sockaddr)) * (IW_MAX_SPY)];
00299 
00300         /* Get monitored addresses from the kernel */
00301         monitored = dyn_wireless_iwspy_get(dev->sock, dev->ifname, buffer);
00302         if (monitored == -1) {
00303                 DEBUG(DEBUG_FLAG,"monitor: get monitored addresses failed\n");
00304                 return -1;
00305         }
00306         hw = (struct sockaddr *)buffer;
00307         qual = (struct iw_quality *)
00308                 (buffer + (sizeof(struct sockaddr) * monitored));
00309 
00310         /* Check if it's already monitored. */
00311         /* FIX: add support for multiple IP addresses for each hw address */
00312         for (i = 0; i < MAX_MONITOR; i++) {
00313                 if (dev->mon[i].active == 0) /* not initialized */
00314                         continue;
00315                 if (adv->addr.s_addr == dev->mon[i].adv->addr.s_addr ||
00316                     !memcmp(adv->adv.from.sll_addr,
00317                             dev->mon[i].adv->adv.from.sll_addr, ETH_ALEN)) {
00318                         DEBUG(DEBUG_FLAG, "monitor: already monitoring %s\n",
00319                               inet_ntoa(dev->mon[i].adv->addr));
00320                         update_statistics(hw, qual, tstamp, dev, monitored); 
00321                         return -3;
00322                 }
00323         }
00324 
00325         /* NEW ENTRY: */
00326 
00327         /* Room for the entry? */
00328         ph = get_free_slot(&tstamp, dev);
00329         if (ph < 0)  { 
00330                 DEBUG(DEBUG_FLAG, "monitor: worst entry was current fa\n");
00331                 return -2; /* No, the worst entry was current FA */
00332         }
00333 
00334         /* Initialize and store values to local data structure */
00335         memset(&dev->mon[ph], 0, sizeof(struct monitor_address));
00336         memset(dev->mon[ph].q10, MAXINT, sizeof(dev->mon[ph].q10));
00337         assert(adv != NULL);
00338         if (dev->mon[ph].adv != NULL) /* if we replace the worst entry */
00339                 dev->mon[ph].adv->mon = NULL; /* then reset the old pointer */
00340         dev->mon[ph].adv = adv;  /* pointer to data in MN */
00341         dev->mon[ph].adv->mon = &dev->mon[ph];
00342         dev->mon[ph].added.tv_sec = tstamp.tv_sec;
00343         dev->mon[ph].added.tv_usec = tstamp.tv_usec;
00344         dev->mon[ph].active = 1;
00345         update_statistics(hw, qual, tstamp, dev, monitored); 
00346 
00347         if (mon_conf.SQ_cache) {
00348                 if (dev->spy_number < MAX_MONITOR)
00349                         dev->spy_number++;
00350                 return ph;
00351         }
00352 
00353         /* SET THE NEW ENTRY TO THE KERNEL WITH SIOCSIWSPY: */
00354 
00355         if (monitored < MAX_KERNEL) {
00356                 memcpy((char *)hw[monitored].sa_data, 
00357                        (char *)adv->adv.from.sll_addr, ETH_ALEN);
00358                 monitored++;
00359         } else {
00360                 /* working set is full, replace worst entry */
00361                 for (i = 0; i < monitored; i++) {
00362                         if (dev != NULL && dev->mon[ph].adv != NULL &&
00363                             memcmp((char *)hw[i].sa_data,
00364                                    (char *)dev->mon[ph].adv->adv.from.sll_addr,
00365                                    ETH_ALEN) == 0) {
00366                                 /* replace hw address */
00367                                 DEBUG(DEBUG_FLAG, "monitor: Replace "
00368                                       "worst entry buffer\n");
00369                                 memcpy((char *)hw[i].sa_data,
00370                                        (char *)adv->adv.from.sll_addr,
00371                                        ETH_ALEN);
00372                                 break;
00373                         }
00374                 }
00375         }
00376         /* Send addresses to the driver */
00377         ret = dyn_wireless_iwspy_set(dev->sock, dev->ifname, 
00378                                      buffer, monitored);
00379         if (ret == -1) {
00380                 DEBUG(DEBUG_FLAG, "Call to dyn_wireless_iwspy_set failed\n");
00381                 return -1;
00382         }
00383         if (dev->spy_number < MAX_MONITOR)
00384                 dev->spy_number++;
00385 
00386         return ph;
00387 }
00388 
00389 
00390 /* 
00391  * Stop monitoring NODE
00392  * 
00393  * Parameters:
00394  *   dev       Interface structure
00395  *   addr      Node's IP address
00396  *
00397  * returns:
00398  *    0        success
00399  *   -1        set iwspy failed
00400  *   -2        device entry not found
00401  */
00402 static int demonitor(struct monitor_interface *dev, struct in_addr addr)
00403 { 
00404         int monitored, i, j, found = -1, ret;
00405         struct sockaddr *hw_set, *hw_get;
00406         char buffer_get[(sizeof(struct iw_quality) +
00407                      sizeof(struct sockaddr)) * (IW_MAX_SPY)];
00408         char buffer_set[(sizeof(struct iw_quality) +
00409                      sizeof(struct sockaddr)) * (IW_MAX_SPY)];
00410 
00411         /* Find the entry from the local structure and mark unused */
00412         for (i = 0; i < MAX_MONITOR; i++) {
00413                 if (dev->mon[i].active == 0) /* not initialized */
00414                         continue;
00415                 assert(dev->mon[i].adv != NULL);
00416                 if (dev->mon[i].adv->addr.s_addr == addr.s_addr) {
00417                         dev->mon[i].active =  0;
00418                         dev->mon[i].adv->mon = NULL;
00419                         found = i;
00420                         break;
00421                 }
00422         }
00423 
00424         if (found == -1) {
00425                 DEBUG(DEBUG_FLAG,
00426                       "monitor_del_fa: Entry not found! (%s)\n",
00427                       dev->ifname);
00428                 return -2;
00429         }
00430 
00431 #ifndef IWSPY_SIM
00432         /* Get entries from the kernel */
00433         monitored = dyn_wireless_iwspy_get(dev->sock, dev->ifname, buffer_get);
00434         hw_get = (struct sockaddr *)buffer_get;
00435         hw_set = (struct sockaddr *)buffer_set;
00436 
00437         /* Take the unused entry away */
00438         DEBUG(DEBUG_FLAG, "monitor_del_fa: Remove entry from the "
00439               "buffer (%d/%d)\n", found, monitored);
00440         assert(dev->mon[found].adv != NULL);
00441         for (i = 0, j = 0; i < monitored; i++) {
00442                 if ((memcmp((unsigned char *)(hw_get[i].sa_data),
00443                             (unsigned char *)
00444                             (dev->mon[found].adv->adv.from.sll_addr),
00445                             ETH_ALEN)) != 0) {
00446                         memcpy((char *)(hw_set[j].sa_data), 
00447                                (char *)(hw_get[i].sa_data),
00448                                ETH_ALEN);
00449                         j++;
00450                 }
00451         }
00452 
00453         /* Reset kernel iwspy entries */
00454         ret = dyn_wireless_iwspy_set(dev->sock, dev->ifname, buffer_set, j);
00455         if (ret) {
00456                 DEBUG(DEBUG_FLAG, "dyn_wireless_iwspy_set failed (%s)\n",
00457                       dev->ifname);
00458                 return -1;
00459         }
00460 #endif /* IWSPY_SIM */
00461 
00462         return 0;
00463 }
00464 
00465 
00466 /*
00467  * This function removes the kernel entry and also the entry from the
00468  * local structure. Called from the MN when agent advertisement expires.
00469  *
00470  * return:
00471  *    0 success
00472  *   -1 not a wireless interface
00473  *   -2 not found
00474  */
00475 static int monitor_del_fa(void *data)
00476 {
00477         struct agentadv_data *adv = NULL;
00478         struct monitor_interface *dev;
00479 
00480         if (data) {
00481                 adv = ((struct event_FA *)data)->adv;
00482         }
00483 
00484         if (adv == NULL)
00485                 return -1;
00486 
00487         DEBUG(DEBUG_FLAG, "monitor_del_fa: %s\n",
00488               inet_ntoa(adv->addr));
00489 
00490         /* Check if interface has wireless extensions */
00491         dev = monitor_get_dev(adv->ifname);
00492         if (!dev || !dev->iwspy_support) {
00493                 DEBUG(DEBUG_FLAG, "monitor_del_fa: Not a wireless "
00494                       "interface (%s)\n", adv->ifname);
00495                 return 1;
00496         }
00497 
00498         return demonitor(dev, adv->addr);
00499 }
00500 
00501 
00502 /*
00503  * Updates current device and FA index. If INTERVA_2_ADV policy is on then
00504  * use own agent advertisement expiration. Otherwise let MN handle expiration.
00505  * 
00506  * returns nothing
00507  */
00508 static void mark_new_entries(void)
00509 {
00510         int i, j;
00511         struct timeval timest;
00512         int lifetime = 0;
00513 
00514         gettimeofday(&timest,NULL);
00515 
00516         /* check all interfaces */
00517         for (j = 0; j < MAX_INTERFACES; j++) {
00518                 if (!mon_devs[j].in_use || !mon_devs[j].iwspy_support)
00519                         continue;
00520 
00521                 /* check all entries in this interface */
00522                 for (i = 0; i < MAX_MONITOR; i++) {
00523                         if (mon_devs[j].mon[i].active != 1) {
00524                                 mon_devs[j].vector_update[i] = 0;
00525                                 continue;
00526                         }
00527                         
00528                         /* At the moment MN expires FA advertisements after
00529                            3*interval+1s. */
00530                         if (!monitor_check_policy(EARLY_EXPIRE_BIT)) {
00531                                 /* MN's agent adv. expiration is ok */
00532                                 mon_devs[j].vector_update[i] = 1;
00533                         } else {
00534                                 /* if the entry is older than
00535                                    lifetime*(expiretime/100) seconds
00536                                    then it's considered old and marked
00537                                    "not updated" */
00538                                 /* NOTE: should we limit expiretime 
00539                                    differently */
00540                                 lifetime = (int)
00541                                   (mon_devs[j].mon[i].adv->expire.tv_sec -
00542                                    mon_devs[j].mon[i].adv->last.tv_sec);
00543                                 if ((mon_devs[j].mon[i].updated.tv_sec +
00544                                      ((lifetime*mon_conf.expiretime)/100)) 
00545                                     > timest.tv_sec) {
00546                                         mon_devs[j].vector_update[i] = 1;
00547                                         mon_devs[j].mon[i].active = 1;
00548                                 } else {
00549                                         DEBUG(DEBUG_FLAG, "mark_new_entries: "
00550                                               "inactive (old) entry\n");
00551                                         mon_devs[j].vector_update[i] = 0;
00552                                         /* set priority to 1 */
00553                                         mon_devs[j].mon[i].adv->priority = 1;
00554                                 }
00555                         }
00556                         /* Get current FA index */
00557                         /* Check interface name and FA ip address */
00558                         if (*mon_conf.current_adv != NULL && 
00559                             !strncmp((*mon_conf.current_adv)->ifname,
00560                                      mon_devs[j].ifname, IFNAMSIZ) &&
00561                             (*mon_conf.current_adv)->addr.s_addr ==
00562                             mon_devs[j].mon[i].adv->addr.s_addr) {
00563                                 mon_conf.current_fa = i;
00564                                 memcpy(mon_conf.current_dev, 
00565                                        mon_devs[j].ifname, IFNAMSIZ);
00566                                 DEBUG(DEBUG_FLAG, "mark_new_entries: "
00567                                       "curr.dev %s, curr.fa %d\n",
00568                                       mon_conf.current_dev, 
00569                                       mon_conf.current_fa);
00570                         }
00571                                 
00572                         
00573                         /* NOTE: if current FA is in the wired side OR,
00574                            MN not connected yet, current_fa will be -1 */
00575                 }
00576         }
00577 
00578         return;
00579 }
00580 
00581 
00582 /*
00583  * If NEWEST_FA/NEWEST_ADV policy is on, then check if this FA has just
00584  * appeared. If so choose the FA immediately.
00585  *
00586  * returns:
00587  *   0 don't change FA
00588  *   1 change FA
00589  */
00590 static int test_newest_fa(struct agentadv_data *adv)
00591 {
00592         int i, j;
00593 
00594         if (adv == NULL) {
00595                 DEBUG(DEBUG_FLAG, "NEWEST_FA: test_newest_fa() called with "
00596                       "NULL adv\n");
00597                 return 0;
00598         }
00599 
00600         if (monitor_check_policy(NEWEST_FA_BIT) && adv->counter > 1)
00601                 return 0;
00602 
00603         /* Use FA with newest agent advertisement */
00604         /* Mark the FA with highest priority */
00605         adv->priority = MAXPRIORITY;
00606         DEBUG(DEBUG_FLAG, "mark_best_fa: newly arrived FA agent"
00607               " advertisement (%s) - policy NEWEST_FA\n", 
00608               inet_ntoa(adv->addr));
00609         
00610         /* FIX? Make the other FAs "unavailable" for a moment
00611            so that monitor will not change to the other OLD
00612            entries with better signal quality immediately */
00613         
00614         /* This is not a problem, since monitor will not change
00615            the FA if no other advertisements are heard. Hmm
00616            what if the same FA's advertismeent is heard again
00617            very fast? I mean if the interval of this new FA is
00618            much more smaller than for the older ones. */
00619         
00620         /* SOLUTION: degrade the other priorities to 1. But,
00621            hey what if this new FA will not accept my
00622            registration? What the heck are you using this
00623            policy anyway then? The priority will degrade
00624            exponentially to zero and after that the other FAs
00625            are better than this FA. Yes, because the signal
00626            quality values are not updated if the updated flag
00627            isn't set --> get_iwspy wount mix the entries when
00628            once degraded. Hmm. what about the default
00629            interface priority? Isn't that made the base
00630            priority for interfaces? Yes, damn. Hey, wait a
00631            minute. Isn't the wireless interface priority set
00632            to 1? If so it will not harm us. Heck, we don't even
00633            use the interface priority for wireless
00634            interfaces. So after all the solution seems to be
00635            good in these circumstances. ;) */
00636         
00637         /* Set priority to 1 for other FAs */
00638         DEBUG(DEBUG_FLAG, "NEWEST_FA: priorities\n");
00639         for (i = 0; i < MAX_INTERFACES; i++) {
00640                 if (!mon_devs[i].in_use || !mon_devs[i].iwspy_support || 
00641                     mon_devs[i].spy_number <= 0)
00642                         continue;
00643 
00644                 for (j = 0; j < MAX_MONITOR; j++) {
00645                         if (mon_devs[i].mon[j].active != 1)
00646                                 continue;
00647 
00648                         DEBUG(DEBUG_FLAG, "NEWEST_FA:    FA=%s prio=%i\n",
00649                               inet_ntoa(mon_devs[i].mon[j].adv->addr),
00650                               mon_devs[i].mon[j].adv->priority);
00651 
00652                         if (mon_devs[i].mon[j].adv == adv ||
00653                             mon_devs[i].mon[j].adv->priority <= 1)
00654                                 continue;
00655 
00656                         DEBUG(DEBUG_FLAG, "NEWEST_FA:    setting other FA "
00657                               "priority %i -> 1\n",
00658                               mon_devs[i].mon[j].adv->priority);
00659                         mon_devs[i].mon[j].adv->priority = 1;
00660                 }
00661         }
00662 
00663         return 1; /* change FA - NEWEST_FA */
00664 }
00665 
00666 
00667 /* 
00668  * Sets priority according to the quality level. The quality level is 0 - 100%.
00669  *
00670  * returns nothing:
00671  */
00672 static void prioritize_all(void)
00673 {
00674         int i, j;
00675         int p = mon_conf.dev_priority_percentage;
00676         struct agentadv_data *adv;
00677         struct monitor_address *mon;
00678 
00679         for (i = 0; i < MAX_INTERFACES; i++) {
00680                 if (!mon_devs[i].in_use || !mon_devs[i].iwspy_support || 
00681                     mon_devs[i].spy_number <= 0)
00682                         continue;
00683                 
00684                 for (j = 0; j < MAX_MONITOR; j++) {
00685                         if (mon_devs[i].mon[j].active != 1 ||
00686                             mon_devs[i].mon[j].adv->priority <= 0)
00687                                 continue;
00688 
00689                         adv = mon_devs[i].mon[j].adv;
00690                         assert(adv!=NULL);
00691                         assert(adv->mon != NULL);
00692                         mon = &mon_devs[i].mon[j];
00693                         assert(mon!=NULL);
00694 
00695                         /* prioritize FA */
00696                         adv->priority = (int)(((mon_devs[i].priority*p + 
00697                                    mon->avg*(100-p)))/100.0);
00698 
00699                         /* This downgrade might be moved to general agent
00700                          * advertisement handling (i.e. used also if IWSPY is
00701                          * not in use) */
00702 
00703                         /* downgrade priority if old entry */
00704                         if (monitor_check_policy(EARLY_EXPIRE_BIT) &&
00705                             mon_devs[i].vector_update[j] != 1) {
00706                                 adv->priority = (int)((adv->priority * 
00707                                           (100-mon_conf.old_fa_factor))/100);
00708                                 DEBUG(DEBUG_FLAG, "(%d/%d) Not fresh! %-15s"
00709                                       " prio %d (factor: %d%%)\n", 
00710                                       j+1, MAX_MONITOR, inet_ntoa(adv->addr),
00711                                       adv->priority, mon_conf.old_fa_factor);
00712                         }
00713                         /* When the wireless card is inserted, the
00714                            iwspy entry in the kernel doesn't
00715                            exists. We put priority nonzero to enable
00716                            registration. */
00717                         if (adv->priority == 0) 
00718                                 adv->priority = 1;
00719                 }
00720         }
00721 }
00722 
00723 
00724 /* 
00725  * According to configuration settings (threshold) priorities are balanced
00726  * so that no unnecessary FA changing happens.
00727  *
00728  * returns nothing:
00729  */
00730 static void monitor_balance_prio(void) 
00731 {
00732         int curr_qual, i, j, max_index = -1;
00733         struct monitor_interface *curr_dev = NULL;
00734         struct monitor_interface *max_dev = NULL;
00735         int max_qual = 0;
00736         double d;
00737         
00738         if (mon_conf.current_fa < 0 ||
00739             (*mon_conf.current_adv) == NULL) {
00740                 DEBUG(DEBUG_FLAG, "monitor_balance_prio: current fa "
00741                       "not known\n");
00742                 return;
00743         }
00744 
00745         /* current FA */
00746         curr_dev = monitor_get_dev(mon_conf.current_dev);
00747         if (!curr_dev || !curr_dev->iwspy_support) {
00748                 DEBUG(DEBUG_FLAG, "monitor_balance_prio: currently not "
00749                       "using wireless device\n");
00750                 return;
00751         }
00752         curr_qual = curr_dev->mon[mon_conf.current_fa].avg;
00753         
00754         /* find max link quality */
00755         for (i = 0; i < MAX_INTERFACES; i++) {
00756                 if (mon_devs[i].in_use == 0 ||
00757                     mon_devs[i].iwspy_support == 0 ||
00758                     mon_devs[i].spy_number <= 0)
00759                         continue;
00760                 
00761                 for (j = 0; j < MAX_MONITOR; j++) {
00762                         if (mon_devs[i].mon[j].active != 1)
00763                                 continue;
00764                         if (mon_devs[i].mon[j].avg > max_qual) {
00765                                 max_dev = &mon_devs[i];
00766                                 max_qual = mon_devs[i].mon[j].avg;
00767                                 max_index = j;
00768                         }
00769                 }
00770         }
00771         if (max_index == -1) {
00772                 DEBUG(DEBUG_FLAG, "monitor_balance_prio: no maximum!\n");
00773                 return;
00774         }
00775         assert(max_dev != NULL);
00776 
00777         /* if current quality below min_balance don't balance */
00778         if (curr_dev->mon[mon_conf.current_fa].avg < mon_conf.min_balance) {
00779                 DEBUG(DEBUG_FLAG, "monitor_balance_prio: quality too small."
00780                       " No balancing (quality %d, min_balance %d)\n",
00781                       curr_dev->mon[mon_conf.current_fa].avg,
00782                       mon_conf.min_balance);
00783                 return;
00784         }
00785         /* balance priorities if quality values are near */
00786         if (max_dev->mon[max_index].avg>0)
00787                 d = (double)(((double)curr_dev->mon[mon_conf.current_fa].avg)/
00788                              ((double)max_dev->mon[max_index].avg));
00789         else
00790                 d = 1.0;
00791 
00792         DEBUG(DEBUG_FLAG, "monitor_balance_prio: current=%d, max=%d,"
00793               " divide=%f, (%d)threshold=%f\n",
00794               curr_dev->mon[mon_conf.current_fa].avg, 
00795               max_dev->mon[max_index].avg, d,
00796               mon_conf.threshold, 
00797               (double)(mon_conf.threshold/100.0));
00798         if(d < 1.0 && d > (mon_conf.threshold/100.0) &&
00799            max_dev->mon[max_index].adv->priority > 0) {
00800                 curr_dev->mon[mon_conf.current_fa].adv->priority =
00801                         max_dev->mon[max_index].adv->priority;
00802                 DEBUG(DEBUG_FLAG, "monitor_balance_prio: "
00803                       "Qualities near enough, balancing\n");
00804         }
00805 #ifdef PRINT_ENTRIES /* by default not defined */
00806         print_entries();
00807 #endif /* PRINT_ENTRIES */
00808         return; 
00809 }
00810 
00811 
00812 /*
00813  * Get the best Foreign Agent. First marks fresh FA's and gets the current FA.
00814  * With NEWEST_FA policy is on monitor_get_fa checks if the FA has just 
00815  * appeared and uses that FA. Otherwise all FAs are prioritized and according 
00816  * configuration settings priorities are balanced. This means that there is 
00817  * certain threshold for changing the FAs.
00818  * 
00819  * returns:
00820  *    1    Foreign Agent changed
00821  *    0    No need to change FA
00822  *   -1    on error
00823  */
00824 static int monitor_get_fa(void *data)
00825 {
00826         int i;
00827         struct agentadv_data *adv = NULL;
00828         struct monitor_interface *dev = NULL;
00829 
00830         if (data) {
00831                 adv = ((struct event_FA *)data)->adv;
00832         }
00833 
00834         for (i = 0; i < MAX_INTERFACES; i++) {
00835                 if (!mon_devs[i].in_use || 
00836                     !mon_devs[i].iwspy_support ||
00837                     mon_devs[i].spy_number <= 0)
00838                         continue;
00839         }
00840 
00841         /* Get current FA */
00842         if (*mon_conf.current_adv == NULL)
00843                 DEBUG(DEBUG_FLAG, "monitor_get_fa: Current adv "
00844                       "pointer is NULL\n");
00845         else {
00846                 DEBUG(DEBUG_FLAG, "monitor_get_fa: current_dev %s\n",
00847                       mon_conf.current_dev);
00848                 dev = monitor_get_dev(mon_conf.current_dev);
00849         }
00850 
00851         /* Mark new entries and get current FA index */
00852         mon_conf.current_fa = -1;
00853         mark_new_entries();
00854 
00855         if (dev != NULL && dev->iwspy_support && mon_conf.current_fa != -1 &&
00856             !strncmp(dev->ifname, mon_conf.current_dev, IFNAMSIZ)) {
00857                 DEBUG(DEBUG_FLAG, "current FA: %-15s",
00858                       inet_ntoa(dev->mon[mon_conf.current_fa].adv->addr));
00859                 DEBUG(DEBUG_FLAG, " active %d, prio %d, avg %d\n",
00860                       dev->mon[mon_conf.current_fa].active,
00861                       dev->mon[mon_conf.current_fa].adv->priority,
00862                       dev->mon[mon_conf.current_fa].avg);
00863         } else
00864                 DEBUG(DEBUG_FLAG, "current FA: Not connected or "
00865                       "FA in the non-wireless-extensions interface\n");
00866 
00867         /* update prioritie(s) for FA(s) behind the wireless interface(s) */
00868         if (adv != NULL &&
00869             (monitor_check_policy(NEWEST_FA_BIT) ||
00870              monitor_check_policy(NEWEST_ADV_BIT))) {
00871                 DEBUG(DEBUG_FLAG, "NEWEST_FA/ADV policy\n");
00872                 if (test_newest_fa(adv) && !adv->in_use)
00873                         return 1; 
00874 
00875                 /* with NEWEST_ADV policy, just simply select the newest FA,
00876                    so no need for other policy-based prioritize functions */
00877                 if (monitor_check_policy(NEWEST_ADV_BIT))
00878                         return 0;
00879         }
00880         
00881         prioritize_all();
00882 
00883         if (!monitor_check_policy(EAGER_SWITCH_BIT))
00884                 monitor_balance_prio(); 
00885         else {
00886                 /* allow quick location updates */
00887                 timerclear(mon_conf.reg_send_timer);
00888         }
00889 
00890         return 0;
00891 }
00892 
00893 
00894 /*
00895  * Add the Foreign Agent's address into monitor.
00896  *
00897  * returns:
00898  *    0  on success
00899  *    1  not a wireless interface
00900  *   -1  on error (iwspy)
00901  *   -2  working set is full
00902  */
00903 static int monitor_add_fa(void *data)
00904 {
00905         int ph;
00906         struct agentadv_data *adv = NULL;
00907         struct monitor_interface *dev;
00908         struct timeval tstamp;
00909         struct iw_quality avg_qual;
00910 
00911         if (data) {
00912                 adv = ((struct event_FA *)data)->adv;
00913         }
00914 
00915         /* Check if interface has wireless extensions */
00916         dev = monitor_get_dev(adv->ifname);
00917         if (!dev || !dev->iwspy_support) {
00918                 DEBUG(DEBUG_FLAG, "monitor_add_fa: Not a wireless "
00919                       "interface (%s)\n", adv->ifname);
00920                 return 1;
00921         }
00922 
00923         gettimeofday(&tstamp,NULL);
00924         
00925         /* start monitoring node if it's not monitored yet */
00926         ph = monitor(dev, adv, tstamp);
00927         if (ph < 0 && ph != -3) {
00928                 DEBUG(DEBUG_FLAG, "monitor_add_fa: failed to monitor\n");
00929         } 
00930         if (ph >= 0)
00931                 DEBUG(DEBUG_FLAG, "monitor_add_fa (index=%d): ip: %s -  "
00932                       "hw: %s\n", ph, inet_ntoa(dev->mon[ph].adv->addr),
00933                       ether_hwtoa((unsigned char *)
00934                                   dev->mon[ph].adv->adv.from.sll_addr));
00935 
00936         /* QUALITY RECORDER:  */
00937         if (mon_conf.rec_qual) {
00938                 if (mon_rec_qual_initialized == 0) {
00939                         rec_init();
00940                         mon_rec_qual_initialized = 1;
00941                 }
00942                 avg_qual.qual = get_qual_avg(dev, adv->adv.from.sll_addr);
00943                 avg_qual.level = 0;
00944                 avg_qual.noise = 0;
00945                 if (memcmp(adv->adv.from.sll_addr, 
00946                            ((*mon_conf.current_adv)->adv.from.sll_addr), 
00947                            ETH_ALEN) == 0) {
00948                         DEBUG(DEBUG_FLAG, "monitor_add_fa: add quality "
00949                               "record\n");
00950                         rec_add((char *) adv->adv.from.sll_addr, &avg_qual,
00951                                 &tstamp, adv->addr);
00952                 }
00953         } else if (mon_rec_qual_initialized) {
00954                 DEBUG(DEBUG_FLAG, "monitor_add_fa: dump quality record\n");
00955                 rec_dump(REC_DUMP_TYPE, -1);
00956                 rec_clean_up();
00957                 mon_rec_qual_initialized = 0;
00958         }
00959 
00960         return ph;
00961 }
00962 
00963 
00964 /*
00965  * Opens socket, tests iwspy and channel support. Wireless extensions 
00966  * are supported only in interfaces that support iwspy ioctls. Queries 
00967  * range for wireless parameters.
00968  *
00969  * returns:
00970  *   dev    success
00971  *  NULL    failed
00972  */
00973 static struct monitor_interface *monitor_dev_up(char *ifname)
00974 {
00975         int i, r;
00976         struct monitor_interface *dev = NULL;
00977         char buffer[(sizeof(struct iw_quality) +
00978                      sizeof(struct sockaddr)) *
00979                    (IW_MAX_SPY+1)];
00980 
00981         /* find free slot */
00982         for (i = 0; i < MAX_INTERFACES; i++) {
00983                 if (!mon_devs[i].in_use) {
00984                         memset(&mon_devs[i], 0, 
00985                                sizeof(struct monitor_interface));
00986                         dev = &mon_devs[i];
00987                         break;
00988                 }
00989         }
00990 
00991         if (!dev) {
00992                 DEBUG(DEBUG_FLAG, "monitor_dev_up: Free slots unavailable!\n");
00993                 return NULL;
00994         }
00995 
00996         /* open socket */
00997         dev->sock = dyn_wireless_create_socket();
00998         if (dev->sock < 0) {
00999                 DEBUG(DEBUG_FLAG, "monitor_dev_up - open wireless socket: "
01000                       "%s\n", strerror(errno));
01001                 return NULL;
01002         }
01003 
01004         /* Copy the wireless interface name */
01005         memcpy(dev->ifname, ifname, IFNAMSIZ);
01006         if (dev->ifname == NULL) {
01007                 DEBUG(DEBUG_FLAG, "monitor_dev_up: dev->ifname NULL!\n");
01008                 return NULL;
01009         }
01010 
01011         /* This is only for testing wireless extension support and
01012          * iwspy ioctls support from the kernel */
01013         r = dyn_wireless_iwspy_get(dev->sock, dev->ifname, buffer);
01014         dev->iwspy_support = r == -1 ? 0 : 1;
01015         if (!dev->iwspy_support)
01016                 DEBUG(DEBUG_FLAG, "monitor_dev_up: IWSPY not supported (%s)\n",
01017                       dev->ifname);
01018 
01019 
01020         /* Clean all the iwspy entries from the kernel */
01021         r = dyn_wireless_iwspy_set(dev->sock, dev->ifname, NULL, 0);
01022         dev->iwspy_support = r == -1 ? 0 : 1;
01023         if (!dev->iwspy_support)
01024                 DEBUG(DEBUG_FLAG, "monitor_dev_up: IWSPY not supported (%s)\n",
01025                       dev->ifname);
01026         
01027         /* Get channel and set the default */
01028         dev->channel = dyn_wireless_get_channel(dev->sock, dev->ifname);
01029         dev->channel_support = dev->channel_get_support =
01030                 dev->channel == -1 ? 0 : 1;
01031         if (!dev->channel_support)
01032                 DEBUG(DEBUG_FLAG, "monitor_dev_up: channel query not "
01033                       "supported (%s)\n", dev->ifname);
01034         else
01035                 DEBUG(DEBUG_FLAG, "monitor_dev_up: %s: channel %d\n",
01036                       dev->ifname, dev->channel);
01037 
01038 
01039         if (mon_conf.default_ch >= 1)
01040                 r = dyn_wireless_set_channel(dev->sock, dev->ifname, 
01041                                              mon_conf.default_ch);
01042         else
01043                 r = dyn_wireless_set_channel(dev->sock, dev->ifname, 
01044                                              dev->channel);
01045                 
01046         dev->channel_support = r == -1 ? 0 : 1;
01047         if (!dev->channel_support)
01048                 DEBUG(DEBUG_FLAG, "monitor_dev_up: set channel not "
01049                       "supported (%s)\n", dev->ifname);
01050         else 
01051                 DEBUG(DEBUG_FLAG, "monitor_dev_up: set channel "
01052                       "successful (%s, %d)\n", dev->ifname,
01053                       dev->channel);
01054 
01055         /* Get range of parameters */
01056         if (dyn_wireless_get_range(dev->sock, dev->ifname, &dev->range)) {
01057                 DEBUG(DEBUG_FLAG, "monitor_dev_up: get range of parameters "
01058                       "not supported (%s)\n", dev->ifname);
01059                 /* set default values (?) */
01060 #define MAX_QUAL 92             
01061                 dev->range.max_qual.qual = MAX_QUAL;
01062         } else {
01063                 /* wvlan_cs 1.0.1 driver doesn't report max quality if 
01064                    no entries to monitor in the driver (e.g. spy_number = 0) */
01065                 if (dev->range.max_qual.qual <= 0) {
01066                         DEBUG(DEBUG_FLAG, "monitor_dev_up: max qual value is "
01067                               "ZERO, assuming wvlan_cs driver and using 92 "
01068                               "as the maximum\n");
01069                         dev->range.max_qual.qual = MAX_QUAL;
01070                 }
01071 
01072                 DEBUG(DEBUG_FLAG, "RANGE (%s):\n", dev->ifname);
01073                 DEBUG(DEBUG_FLAG, "\tthroughput          %d\n", 
01074                       dev->range.throughput);
01075                 DEBUG(DEBUG_FLAG, "\tmin_nwid            %d\n", 
01076                       dev->range.min_nwid);
01077                 DEBUG(DEBUG_FLAG, "\tmax_nwid            %d\n", 
01078                       dev->range.max_nwid);
01079                 DEBUG(DEBUG_FLAG, "\tchannels            %d\n", 
01080                       dev->range.num_channels);
01081                 DEBUG(DEBUG_FLAG, "\tsensitivity         %d\n", 
01082                       dev->range.sensitivity);
01083                 DEBUG(DEBUG_FLAG, "\tmax_qual.qual       %d\n", 
01084                       dev->range.max_qual.qual);
01085                 DEBUG(DEBUG_FLAG, "\tmax_qual.level      %d\n", 
01086                       dev->range.max_qual.level);
01087                 DEBUG(DEBUG_FLAG, "\tmax_qual.noise      %d\n", 
01088                       dev->range.max_qual.noise);
01089 
01090 #if WIRELESS_EXT >= 9
01091                 /* FIX: encoding structure changed in wireless ext ver. 9 */
01092 #else
01093                 DEBUG(DEBUG_FLAG, "\tmax_encoding.method %d\n", 
01094                       dev->range.max_encoding.method);
01095 #endif
01096 
01097 #if WIRELESS_EXT >= 8
01098                 DEBUG(DEBUG_FLAG, "\tnum_bitrates        %d\n", 
01099                       dev->range.num_bitrates);
01100                 DEBUG(DEBUG_FLAG, "\tmin_rts             %d\n", 
01101                       dev->range.min_rts);
01102                 DEBUG(DEBUG_FLAG, "\tmax_rts             %d\n", 
01103                       dev->range.max_rts);
01104                 DEBUG(DEBUG_FLAG, "\tmin_frag            %d\n", 
01105                       dev->range.min_frag);
01106                 DEBUG(DEBUG_FLAG, "\tmax_frag            %d\n", 
01107                       dev->range.max_frag);
01108 #endif
01109         }
01110 
01111         dev->in_use = 1;
01112         mon_conf.interfaces++;
01113 
01114         if (!dev->channel_get_support && !dev->channel_support &&
01115             !dev->iwspy_support) {
01116                 close(dev->sock);
01117                 dev->sock = -1;
01118         }
01119 
01120         return dev;
01121 }
01122 
01123 
01124 /*
01125  * Cleans monitored entries from the driver. Decreases counters and closes 
01126  * sockets.
01127  *
01128  * returns:
01129  *   0  success
01130  *  -1  device structure not in use 
01131  */
01132 static int monitor_dev_down(struct monitor_interface *dev)
01133 {
01134         if (dev->in_use) {
01135                 mon_conf.interfaces--;
01136                 dev->in_use = 0;
01137                 if (mon_conf.interfaces < 0) {
01138                         mon_conf.interfaces = 0;
01139                         DEBUG(DEBUG_FLAG, "monitor_dev_down: Negative "
01140                               "interface count!\n");
01141                 }
01142                 if (!dev->iwspy_support) 
01143                         return 0;
01144 
01145                 /* remove iwspy entries from the interface */
01146                 dyn_wireless_iwspy_set(dev->sock, dev->ifname, NULL, 0);
01147                 /* close socket */
01148                 if (dev->sock >= 0) {
01149                         close(dev->sock);
01150                         dev->sock = -1;
01151                 }
01152                 mon_conf.iwspy_supported--;
01153                 if (mon_conf.iwspy_supported < 0) {
01154                         mon_conf.iwspy_supported = 0;
01155                         DEBUG(DEBUG_FLAG, "monitor_dev_down: Negative "
01156                               "iwspy_support count!\n");
01157                 }
01158         } else
01159                 return -1;
01160         
01161         return 0;
01162 }
01163 
01164 
01165 /*
01166  * "event_INTERFACE_UP" event handler
01167  *
01168  * Makes and fill in new interface structure. Register handlers for 
01169  * for this interface.
01170  *
01171  * returns:
01172  *   -1  open socket failed 
01173  *    0  iwspy: YES, channel switch: YES
01174  *    1  iwspy: YES, channel switch: NO
01175  *    2  iwspy: NO,  channel switch: YES
01176  *    3  iwspy: NO,  channel switch: NO
01177  */
01178 static int monitor_interface_up(void *data)
01179 {
01180         struct monitor_interface *dev;
01181         char *ifname = NULL;
01182         struct timeval *last_reg_send_time = NULL;
01183         int *priority = NULL;
01184 
01185         if (data) {
01186                 ifname = ((struct event_INTERFACE *)data)->ifname;
01187                 last_reg_send_time = ((struct event_INTERFACE *)
01188                                       data)->last_reg_send_time;
01189                 mon_conf.current_adv = ((struct event_INTERFACE *)
01190                                          data)->current_adv;
01191                 priority = ((struct event_INTERFACE *)data)->priority;
01192         }
01193         
01194         /* find free slot, if not already initialized */
01195         dev = monitor_dev_up(ifname);
01196         if (dev == NULL) {
01197                 DEBUG(DEBUG_FLAG, "monitor_interface_up: no free slots\n");
01198                 syslog(LOG_ERR, "monitor_interface_up: no free slots, %m");
01199                 return -1;
01200         }
01201         
01202         /* Get pointer to the send timer (we need to set this zero, if 
01203          * location updates are more frequent than 1 second) */
01204         if (mon_conf.reg_send_timer == NULL)
01205                 mon_conf.reg_send_timer = last_reg_send_time;
01206 
01207         /* Register handlers if not already registered */
01208         if (dev->iwspy_support && mon_conf.iwspy_supported == 0) {
01209                 handler_register(FA_ADV_EXPIRE, monitor_del_fa);
01210                 handler_register(FA_ADV_RECEIVE, monitor_add_fa);
01211 #ifndef PLAIN_MIP
01212                 handler_register(FA_GET, monitor_get_fa);
01213 #endif /* PLAIN_MIP */
01214                 mon_conf.iwspy_supported++;
01215                 DEBUG(DEBUG_FLAG, "monitor_interface_up: Handlers "
01216                       "initialized (%s)\n", dev->ifname);
01217                 if (mon_conf.rec_qual) {
01218                         if (mon_rec_qual_initialized == 0) {
01219                                 /* quality recorder only valuable if 
01220                                    iwspy supported */
01221                                 rec_init();
01222                                 mon_rec_qual_initialized = 1;
01223                         }
01224                 } else if (mon_rec_qual_initialized) {
01225                         rec_dump(REC_DUMP_TYPE, -1);
01226                         rec_clean_up();
01227                         mon_rec_qual_initialized = 0;
01228                 }
01229         }
01230         
01231         /* set priority */
01232         if (priority != NULL && *priority >= 0)
01233                 dev->priority = *priority;
01234         else
01235                 if (dev->iwspy_support)
01236                         dev->priority = DEFAULT_WIRELESS_PRIO;
01237                 else
01238                         dev->priority = DEFAULT_INTERFACE_PRIORITY;
01239 
01240 
01241         DEBUG(DEBUG_FLAG, "monitor_interface_up: iwspy: %s channel"
01242               " switch: %s\n", 
01243               dev->iwspy_support   ? "YES" : "NO",
01244               dev->channel_support ? "YES" : "NO");
01245 
01246         if (dev->channel_support && dev->iwspy_support)
01247                 return 0;
01248         else if (!dev->channel_support && dev->iwspy_support)
01249                 return 1;
01250         else if (dev->channel_support && !dev->iwspy_support)
01251                 return 2;
01252         else
01253                 return 3;
01254 }
01255 
01256 
01257 /*
01258  * "event_INTERFACE_DOWN" event handler
01259  * 
01260  * Clears device structures in monitor and unregisters handlers that
01261  * were bound to this interface
01262  * 
01263  * return:
01264  *   0   success
01265  *  -1   failed
01266  */
01267 static int monitor_interface_down(void *data)
01268 {
01269         struct event_INTERFACE *vars = (struct event_INTERFACE *)data;
01270         struct monitor_interface *dev = NULL;
01271 
01272         if (vars == NULL) {
01273                 DEBUG(DEBUG_FLAG, "monitor_interface_down: NULL argument!\n");
01274                 return -1;
01275         }
01276 
01277         dev = monitor_get_dev(vars->ifname);
01278         if (!dev) {
01279                 DEBUG(DEBUG_FLAG, "monitor_interface_down: Device not "
01280                       "found! (%s)\n", vars->ifname);
01281                 return -1;
01282         }
01283 
01284         monitor_dev_down(dev);
01285 
01286         /* unregister event_FA handlers if the only interface */
01287         if (mon_conf.iwspy_supported == 0 && dev->iwspy_support) {
01288                 handler_unregister(FA_ADV_EXPIRE, monitor_del_fa);
01289                 handler_unregister(FA_ADV_RECEIVE, monitor_add_fa);
01290 #ifndef PLAIN_MIP
01291                 handler_unregister(FA_GET, monitor_get_fa);
01292 #endif /* PLAIN_MIP */
01293         }
01294 
01295         return 0;
01296 }
01297 
01298 
01299 /***********************/
01300 /* MODULE registration */
01301 /***********************/
01302 
01303 int MONITOR_unregister_module(void)
01304 {
01305         int i;
01306 
01307         for (i = 0; i < MAX_INTERFACES; i++) {
01308                 if (!mon_devs[i].in_use)
01309                         continue;
01310                 if (mon_devs[i].iwspy_support && !mon_conf.SQ_cache)
01311                         dyn_wireless_iwspy_set(mon_devs[i].sock, 
01312                                                mon_devs[i].ifname, NULL, 0);
01313 
01314                 if (mon_devs[i].sock >= 0) {
01315                         close(mon_devs[i].sock);
01316                         mon_devs[i].sock = -1;
01317                 }
01318         }
01319 
01320         if (mon_rec_qual_initialized) {
01321                 if (mon_conf.rec_qual)
01322                         rec_dump(REC_DUMP_TYPE, -1);
01323                 rec_clean_up();
01324                 mon_rec_qual_initialized = 0;
01325         }
01326 
01327         return 0;
01328 }
01329 
01330 
01331 void MONITOR_register_module(void)
01332 {
01333         /* initialize state and variables */
01334         memset(&mon_conf, 0, sizeof(struct monitor_global_data));
01335         mon_conf.current_fa = -1;    /* not connected yet */
01336         mon_conf.current_adv = NULL;
01337         mon_conf.reg_send_timer = NULL;
01338         mon_conf.interfaces = 0;
01339         mon_conf.iwspy_supported = 0;
01340         mon_conf.threshold = DEFAULT_THRESHOLD;
01341         mon_conf.default_ch = -1;
01342         mon_conf.old_fa_factor = OLD_FA_FACTOR;
01343         mon_conf.expiretime = DEFAULT_EARLY_EXPIRE_TIME;
01344         mon_conf.min_balance = DEFAULT_MIN_BALANCE;
01345         mon_conf.worst_min_time = DEFAULT_WORST_MIN_TIME;
01346         mon_conf.worst_max_time = DEFAULT_WORST_MAX_TIME;
01347         mon_conf.dev_priority_percentage = DEFAULT_DEV_PRIO_PERCENT;
01348         mon_conf.average_length = DEFAULT_AVG_LEN;
01349         mon_conf.rec_qual = 0;
01350         mon_conf.SQ_cache = 0;
01351         mon_rec_qual_initialized = 0;
01352         memset(mon_devs, 0, sizeof(mon_devs));
01353 
01354         /* register event_INTERFACE handlers */
01355         handler_register(INTERFACE_INIT, monitor_interface_up);
01356         handler_register(INTERFACE_DOWN, monitor_interface_down);
01357 }
01358 
01359 
01360 void monitor_poll_ap_addresses(struct mn_data *mn)
01361 {
01362         int i, j;
01363         char new_addr[ETH_ALEN];
01364 
01365         DEBUG(DEBUG_FLAG, "monitor_poll_ap_addresses()\n");
01366         for (i = 0; i < MAX_INTERFACES; i++) {
01367                 if (!mon_devs[i].in_use || mon_devs[i].sock < 0)
01368                         continue;
01369 
01370                 if (dyn_wireless_get_ap_address(mon_devs[i].sock,
01371                                                 mon_devs[i].ifname,
01372                                                 new_addr) < 0) {
01373                         DEBUG(DEBUG_FLAG, "monitor_poll_ap_addresses: get AP "
01374                               "hw addr failed\n");
01375                         continue;
01376                 }
01377 
01378                 if (memcmp(new_addr, mon_devs[i].ap_hwaddr, ETH_ALEN) != 0) {
01379                         DEBUG(DEBUG_FLAG, "Monitor: AP hw addr changed "
01380                               "(iface=%s): %s => ",
01381                               mon_devs[i].ifname,
01382                               ether_hwtoa((unsigned char *)
01383                                           mon_devs[i].ap_hwaddr));
01384                         DEBUG(DEBUG_FLAG, "%s\n",
01385                               ether_hwtoa((unsigned char *) new_addr));
01386                         /* send agentsol to this interface */
01387                         for (j = 0; j < MAX_INTERFACES; j++) {
01388                                 if (strcmp(mon_devs[i].ifname,
01389                                            mn->iface[j].device) != 0 ||
01390                                     mn->iface[j].s < 0)
01391                                         continue;
01392 
01393                                 send_agent_solicitation(mn->iface[j].s);
01394                         }
01395                         memcpy(mon_devs[i].ap_hwaddr, new_addr, ETH_ALEN);
01396                 }
01397         }
01398 }

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