monitube2-data_config.c

Go to the documentation of this file.
00001 /*
00002  * $Id: monitube2-data_config.c 347265 2009-11-19 13:55:39Z kdickman $
00003  *
00004  * This code is provided as is by Juniper Networks SDK Developer Support.
00005  * It is provided with no warranties or guarantees, and Juniper Networks
00006  * will not provide support or maintenance of this code in any fashion.
00007  * The code is provided only to help a developer better understand how
00008  * the SDK can be used.
00009  *
00010  * Copyright (c) 2009, Juniper Networks, Inc.
00011  * All rights reserved.
00012  */
00013 
00023 #include "monitube2-data_main.h"
00024 #include "monitube2-data_config.h"
00025 
00026 
00027 /*** Constants ***/
00028 
00029 #define MONITUBE2_MGMT_STRLEN  256     
00030 
00031 #define RLOCK(l) INSIST_ERR(msp_rwlock_rlock(l) == MSP_OK) 
00032 
00033 #define WLOCK(l) INSIST_ERR(msp_rwlock_wlock(l) == MSP_OK) 
00034 
00035 #define RUNLOCK(l) INSIST_ERR(msp_rwlock_runlock(l) == MSP_OK) 
00036 
00037 #define WUNLOCK(l) INSIST_ERR(msp_rwlock_wunlock(l) == MSP_OK) 
00038 
00039 /*** Data structures ***/
00040 
00044 extern int plugin_id;
00045 
00049 extern evContext * ctx;
00050 
00054 extern msp_policy_db_handle_t pdb_handle;
00055 
00059 extern void * pdb_shm_handle;
00060 
00064 typedef struct list_item_s {
00065         void * data; 
00066     TAILQ_ENTRY(list_item_s) entries; 
00067 } list_item_t;
00068 
00069 
00070 typedef TAILQ_HEAD(list_s, list_item_s) list_t; 
00071 
00072 
00078 typedef struct ss_info_s {
00079     uint16_t     id;        
00080     u_int32_t    svc_id;    
00081     u_int32_t    gen_num;   
00082     radix_root_t prefixes;  
00083     msp_rwlock_t prefixes_lock; 
00084     list_t       rules;     
00085 } ss_info_t;
00086 
00087 
00092 typedef struct address_s {
00093     patnode    node;       
00094     in_addr_t  address;    
00095     in_addr_t  mask;       
00096 } address_t;
00097 
00098 
00109 typedef struct rule_s {
00110     patnode    node;                
00111     char       name[MONITUBE2_MGMT_STRLEN];  
00112     uint32_t   rate;                
00113     in_addr_t  redirect;            
00114     patroot *  addresses;           
00115     list_t     ssets;               
00116     
00117     msp_rwlock_t lock;              
00118 } rule_t;
00119 
00120 
00125 typedef struct prefix_s {
00126     rnode_t     rnode;        
00127     in_addr_t   prefix;       
00128     rule_t *    rule;         
00129 } prefix_t;
00130 
00131 
00136 static atomic_uint_t current_time;
00137 
00138 
00142 static patroot rules;
00143 
00144 
00145 /*** STATIC/INTERNAL Functions ***/
00146 
00151 PATNODE_TO_STRUCT(rule_entry, rule_t, node)
00152 
00153 
00154 
00158 PATNODE_TO_STRUCT(address_entry, address_t, node)
00159 
00160 
00176 static void
00177 update_time(evContext ectx UNUSED,
00178             void * uap  UNUSED,
00179             struct timespec due UNUSED,
00180             struct timespec inter UNUSED)
00181 {
00182     atomic_add_uint(1, &current_time);
00183 }
00184 
00185 
00194 static uint8_t
00195 bit_count(uint32_t n)
00196 {
00197     register unsigned int tmp;
00198 
00199     tmp = n - ((n >> 1) & 033333333333)
00200             - ((n >> 2) & 011111111111);
00201     return ((tmp + (tmp >> 3)) & 030707070707) % 63;
00202 }
00203 
00204 
00220 static void
00221 free_policy(evContext ectx UNUSED,
00222             void * uap,
00223             struct timespec due UNUSED,
00224             struct timespec inter UNUSED)
00225 {
00226     ss_info_t * ssi = (ss_info_t *)uap;
00227         list_item_t * item;
00228         prefix_t * p;
00229         rnode_t * r;
00230         
00231     // Empty the rules list and the prefixes rtree
00232         // should be no readers of the prefixes by this delayed point
00233     
00234         while((r = radix_find_next(&ssi->prefixes, NULL)) != NULL) {
00235                 radix_delete(&ssi->prefixes, r);
00236                 p = (prefix_t *)((uint8_t *)r - offsetof(prefix_t, rnode));
00237                 msp_shm_free(pdb_shm_handle, p);
00238         }
00239         
00240     while((item = TAILQ_FIRST(&ssi->rules)) != NULL) {
00241         TAILQ_REMOVE(&ssi->rules, item, entries);
00242         msp_shm_free(pdb_shm_handle, item);
00243     }
00244         
00245         msp_shm_free(pdb_shm_handle, ssi);
00246 }
00247 
00248 /*** GLOBAL/EXTERNAL Functions ***/
00249 
00250 
00256 void
00257 init_config(void)
00258 {
00259     patricia_root_init(&rules, FALSE, MONITUBE2_MGMT_STRLEN, 0);
00260 
00261     current_time = (atomic_uint_t)(time(NULL) - 1);
00262 
00263     // cached system time
00264     if(evSetTimer(*ctx, update_time, NULL, evNowTime(), evConsTime(1,0), NULL)) {
00265         CLOG(LOG_EMERG, "%s: Failed to initialize an eventlib timer to generate "
00266             "the cached time", __func__);
00267     }
00268 }
00269 
00270 
00277 time_t
00278 get_current_time(void)
00279 {
00280     return (time_t)current_time;
00281 }
00282 
00283 
00287 void
00288 clear_config(void)
00289 {
00290     msp_policy_db_params_t policy_db_params;
00291         msp_policy_db_svc_set_key_t key, next_key;
00292         rule_t * rule;
00293     ss_info_t * ssi;
00294         
00295         // First we delete the service set policies, then the rules
00296         
00297         bzero(&key, sizeof(msp_policy_db_svc_set_key_t));
00298         bzero(&next_key, sizeof(msp_policy_db_svc_set_key_t));
00299         bzero(&policy_db_params, sizeof(msp_policy_db_params_t));
00300         
00301         policy_db_params.handle = pdb_handle;
00302         policy_db_params.plugin_id = plugin_id;
00303         strlcpy(policy_db_params.plugin_name, PLUGIN_NAME,
00304                         sizeof(policy_db_params.plugin_name));
00305         
00306         while(msp_policy_db_get_next_svc_set_id(
00307                         pdb_handle, &key, &next_key) == EOK) {
00308                 
00309                 policy_db_params.svc_set_id = next_key.svc_set_id;
00310                 policy_db_params.svc_id = next_key.svc_id;
00311                 policy_db_params.policy_op = MSP_POLICY_DB_POLICY_GET;
00312 
00313                 if (msp_policy_db_op(&policy_db_params) != MSP_OK) {
00314                         CLOG(LOG_INFO, "%s: No PDB configuration found", __func__);
00315                 key.svc_set_id = next_key.svc_set_id;
00316                 key.svc_id = next_key.svc_id;
00317                         continue;
00318                 }
00319                 
00320                 ssi = policy_db_params.op.get_params.policy;
00321                 
00322                 if (ssi) {
00323                         
00324                         // Delete the policy for the service set
00325                         
00326                         policy_db_params.policy_op = MSP_POLICY_DB_POLICY_DEL;
00327                         policy_db_params.op.del_params.gen_num = ssi->gen_num;
00328                         
00329                         if (msp_policy_db_op(&policy_db_params) != MSP_OK) {
00330                                 CLOG(LOG_ERR, "%s: PDB Delete failed!", __func__);
00331                                 return;
00332                         }
00333                         
00334                     // delay the free of the policy in case someone did a GET op and 
00335                         // is using it make some random delay between 5-15 secs so there's 
00336                         // not too many frees at once (since it uses some locking in the shm
00337                         // pool) in case we're clearing a lot
00338                         
00339                     if (evSetTimer(*ctx, free_policy, ssi, evAddTime(evNowTime(),
00340                         evConsTime(5 + (rand() % 11), 0)), evConsTime(0, 0), NULL)) {
00341 
00342                         CLOG(LOG_EMERG, "%s: Failed to initialize a timer to free the "
00343                                         "policy (Error: %m)", __func__);
00344                     }
00345                 }
00346 
00347                 key.svc_set_id = next_key.svc_set_id;
00348                 key.svc_id = next_key.svc_id;
00349         }
00350 
00351     while((rule = rule_entry(patricia_find_next(&rules, NULL)))) {
00352         
00353         // use delete_rule() which safely remove references from any
00354         // service sets' prefixes to this rule
00355         
00356         if(delete_rule(rule->name)) {
00357                 CLOG(LOG_ERR, "%s: Cannot finish deleting the rules", __func__);
00358                 break; // on failure
00359         }
00360     }
00361 }
00362 
00363 
00376 void
00377 update_rule(char * name, uint32_t rate, in_addr_t redirect)
00378 {
00379         rule_t * rule;
00380         
00381     rule = rule_entry(patricia_get(&rules, strlen(name) + 1, name));
00382     
00383     if(rule == NULL) {
00384         rule = msp_shm_alloc(pdb_shm_handle, sizeof(rule_t));
00385         INSIST_ERR(rule != NULL);
00386         strlcpy(rule->name, name, sizeof(rule->name));
00387 
00388         // Add to patricia tree
00389         patricia_node_init_length(&rule->node, strlen(name) + 1);
00390 
00391         // init addresses
00392         rule->addresses = patricia_root_init(NULL, FALSE, sizeof(in_addr_t), 0);
00393         TAILQ_INIT(&rule->ssets);
00394         INSIST_ERR(msp_rwlock_init(&rule->lock) == MSP_OK);
00395         
00396         rule->rate = rate;
00397         rule->redirect = redirect;
00398         
00399         if(!patricia_add(&rules, &rule->node)) {
00400             CLOG(LOG_ERR, "%s: Failed to add rule to configuration", __func__);
00401             free(rule);
00402         }
00403 
00404         return;        
00405     }
00406     
00407     WLOCK(&rule->lock);
00408     rule->rate = rate;
00409     rule->redirect = redirect;
00410     WUNLOCK(&rule->lock);
00411 }
00412 
00413 
00422 int
00423 delete_rule(char * name)
00424 {
00425         rule_t * rule;
00426         address_t * a;
00427     ss_info_t * ssi;
00428         rnode_t * rn;
00429         prefix_t * prefix;
00430         list_item_t * item;
00431         
00432     rule = rule_entry(patricia_get(&rules, strlen(name) + 1, name));
00433     
00434     if(rule == NULL) {
00435         CLOG(LOG_ERR, "%s: Cannot find the rule %s", __func__, name);
00436         return -1;
00437     }
00438     
00439         if(!patricia_delete(&rules, &rule->node)) {
00440                 CLOG(LOG_ERR, "%s: Failed to delete rule from configuration", __func__);
00441                 return -1;
00442         }
00443     
00444     WLOCK(&rule->lock); // wait for any readers to finish
00445         
00446         // Delete ssets and references from those sets to this rule
00447         
00448     while((item = TAILQ_FIRST(&rule->ssets)) != NULL) {
00449         ssi = item->data; // this sset applies this rule
00450                 TAILQ_REMOVE(&rule->ssets, item, entries);
00451                 msp_shm_free(pdb_shm_handle, item);
00452                 
00453                 // remove reference to this rule
00454                 
00455             item = TAILQ_FIRST(&ssi->rules);
00456             while(item != NULL) {
00457                 if (item->data == rule) {
00458                         TAILQ_REMOVE(&ssi->rules, item, entries);
00459                         msp_shm_free(pdb_shm_handle, item);
00460                         break;
00461                 }
00462                 item = TAILQ_NEXT(item, entries);
00463             }
00464             
00465             // remove any prefixes in this service set coming from this rule
00466             
00467             a = address_entry(patricia_find_next(rule->addresses, NULL));
00468             while(a != NULL) {
00469                 
00470                 rn = radix_get(&ssi->prefixes, bit_count(a->mask),
00471                                 (uint8_t *)&a->address);
00472 
00473                 if(rn != NULL) {
00474                     prefix = (prefix_t *)((uint8_t *)rn - offsetof(prefix_t,rnode));
00475                     
00476                         if(prefix->rule == rule) {
00477                                 WLOCK(&ssi->prefixes_lock);
00478                                 
00479                                 radix_delete(&ssi->prefixes, rn);
00480                                 
00481                                 WUNLOCK(&ssi->prefixes_lock);
00482                         }
00483                 }
00484                 
00485                 a = address_entry(patricia_find_next(rule->addresses, &a->node));
00486             }
00487             
00488     }
00489     
00490     // delete all addresses
00491 
00492     while((a = address_entry(patricia_find_next(rule->addresses, NULL)))) {
00493         patricia_delete(rule->addresses, &a->node);
00494         free(a);
00495     }
00496     
00497     patricia_root_delete(rule->addresses);
00498 
00499         // delete rule
00500     
00501         msp_shm_free(pdb_shm_handle, rule);
00502         return 0;
00503 }
00504 
00505 
00518 void
00519 add_address(char * name, in_addr_t addr, in_addr_t mask)
00520 {
00521         rule_t * rule;
00522         address_t * address;
00523         ss_info_t * ssi;
00524         prefix_t * prefix;
00525         list_item_t * item;
00526         
00527     rule = rule_entry(patricia_get(&rules, strlen(name) + 1, name));
00528     
00529     if(rule == NULL) {
00530         CLOG(LOG_ERR, "%s: Cannot find the rule %s", __func__, name);
00531         return;
00532     }
00533     
00534     // address won't be SHM b/c it's never accessed in fast path
00535     address = calloc(1, sizeof(address_t));
00536     INSIST_ERR(address != NULL);
00537 
00538     address->address = addr;
00539     address->mask = mask;
00540 
00541     // Add to patricia tree
00542     
00543     patricia_node_init(&address->node);
00544 
00545     if(!patricia_add(rule->addresses, &address->node)) {
00546         CLOG(LOG_ERR, "%s: Cannot add address %08X / %08X as it conflicts with"
00547             " another address in the same rule (%s)", __func__, addr, mask, name);
00548         free(address);
00549     }
00550     
00551     // Ssets using this rule need their radix tree updated
00552     
00553     item = TAILQ_FIRST(&rule->ssets);
00554     while(item != NULL) {
00555         ssi = item->data;
00556         
00557         prefix = msp_shm_alloc(pdb_shm_handle, sizeof(prefix_t));
00558         INSIST_ERR(prefix != NULL);
00559         prefix->prefix = addr;
00560         prefix->rule = rule;
00561 
00562         radix_node_init(&prefix->rnode, bit_count(mask), 0);
00563 
00564         WLOCK(&ssi->prefixes_lock);
00565         
00566         if(radix_add(&ssi->prefixes, &prefix->rnode)) {
00567                 WUNLOCK(&ssi->prefixes_lock);
00568             msp_shm_free(pdb_shm_handle, prefix);
00569             CLOG(LOG_ERR, "%s: Failed to add prefix to rtree configuration."
00570                         " Could be due to a duplicate prefix.", __func__);
00571         } else {
00572                 WUNLOCK(&ssi->prefixes_lock);
00573         }
00574     }
00575 }
00576 
00577 
00590 void
00591 delete_address(char * name, in_addr_t addr, in_addr_t mask)
00592 {
00593         rule_t * rule;
00594         address_t * address;
00595         rnode_t * rn;
00596         ss_info_t * ssi;
00597         prefix_t * prefix;
00598         list_item_t * item;
00599         
00600         
00601     rule = rule_entry(patricia_get(&rules, strlen(name) + 1, name));
00602     
00603     if(rule == NULL) {
00604         CLOG(LOG_ERR, "%s: Cannot find the rule %s", __func__, name);
00605         return;
00606     }
00607 
00608     address = address_entry(patricia_get(rule->addresses,
00609                     sizeof(in_addr_t), &addr));
00610 
00611     if(address == NULL) {
00612         CLOG(LOG_ERR, "%s: Could not find address to delete",__func__);
00613         return;
00614     }
00615 
00616     if(!patricia_delete(rule->addresses, &address->node)) {
00617         CLOG(LOG_ERR, "%s: Deleting address failed", __func__);
00618         return;
00619     }
00620     
00621     // Ssets using this rule need their radix tree updated
00622     
00623     item = TAILQ_FIRST(&rule->ssets);
00624     while(item != NULL) {
00625         ssi = item->data;
00626         
00627         rn = radix_get(&ssi->prefixes, bit_count(mask), (uint8_t *)&addr);
00628 
00629         if(rn == NULL) {
00630             CLOG(LOG_ERR, "%s: Failed to find prefix to remove from "
00631                     "rtree configuration", __func__);
00632         } else {
00633             prefix = (prefix_t *)((uint8_t *)rn - offsetof(prefix_t, rnode));
00634                 if(prefix->rule != rule) {
00635                 CLOG(LOG_WARNING, "%s: Prefix in the rtree doesn't belong to "
00636                                         "this rule. Could be due to a duplicate prefix.", __func__);
00637                 } else {
00638                         WLOCK(&ssi->prefixes_lock);
00639                         
00640                         radix_delete(&ssi->prefixes, rn);
00641                         
00642                         WUNLOCK(&ssi->prefixes_lock);
00643                 }
00644         }
00645     }
00646     
00647     free(address);
00648 }
00649 
00650 
00666 void
00667 apply_rule(char * name, uint16_t ssid, uint32_t gennum, uint32_t svcid)
00668 {
00669     msp_policy_db_params_t policy_db_params;
00670     ss_info_t * ssi;
00671     rule_t * rule;
00672     list_item_t * item;
00673 
00674         if(svcid && svcid != MSP_SVC_ID_SERVICES) {
00675                 CLOG(LOG_ERR, "%s: Found unexpected service id: %d", __func__, svcid);
00676         }
00677         
00678         bzero(&policy_db_params, sizeof(msp_policy_db_params_t));
00679         
00680         // Get the current policy for the service set
00681         
00682         policy_db_params.handle = pdb_handle;
00683         policy_db_params.svc_set_id = ssid;
00684         policy_db_params.svc_id = svcid;
00685         policy_db_params.plugin_id = plugin_id;
00686         policy_db_params.policy_op = MSP_POLICY_DB_POLICY_GET;
00687         strlcpy(policy_db_params.plugin_name, PLUGIN_NAME,
00688                         sizeof(policy_db_params.plugin_name));
00689 
00690         if (msp_policy_db_op(&policy_db_params) != MSP_OK) {
00691             CLOG(LOG_INFO, "%s: No PDB configuration found", __func__);
00692             ssi = NULL;
00693         } else {
00694             ssi = policy_db_params.op.get_params.policy;    
00695         }
00696             
00697         if(ssi == NULL) {
00698                 // Add to the PDB for this service set
00699                 
00700                 ssi = msp_shm_alloc(pdb_shm_handle, sizeof(ss_info_t));
00701                 if(!ssi) {
00702                         CLOG(LOG_ALERT, "%s: Cannot allocate into policy SHM...", __func__);
00703                         return;
00704                 }
00705                 
00706                 ssi->id = ssid;
00707                 ssi->svc_id = svcid;
00708                 ssi->gen_num = gennum;
00709                 radix_init_root(&ssi->prefixes);
00710                 TAILQ_INIT(&ssi->rules);
00711                 INSIST_ERR(msp_rwlock_init(&ssi->prefixes_lock) == MSP_OK);
00712             
00713                 bzero(&policy_db_params, sizeof(msp_policy_db_params_t));
00714                 
00715                 // Populate the policy database
00716                 
00717                 // General params
00718                 policy_db_params.handle = pdb_handle;
00719                 policy_db_params.svc_set_id = ssid;
00720                 policy_db_params.svc_id = svcid;
00721                 policy_db_params.plugin_id = plugin_id;
00722                 policy_db_params.policy_op = MSP_POLICY_DB_POLICY_ADD;
00723                 strlcpy(policy_db_params.plugin_name, PLUGIN_NAME,
00724                                 sizeof(policy_db_params.plugin_name));
00725 
00726                 // Add-specific params
00727                 policy_db_params.op.add_params.gen_num = gennum;
00728                 policy_db_params.op.add_params.policy = ssi;
00729                 
00730                 if (msp_policy_db_op(&policy_db_params) != MSP_OK) {
00731                         CLOG(LOG_ERR, "%s: Policy DB Add failed!", __func__);
00732                 }
00733         } else if (gennum != ssi->gen_num) {
00734                 CLOG(LOG_ERR, "%s: Generation number %d is out of sync with what is"
00735                                 "currently in the policy DB %d for this service set %d",
00736                                 __func__, gennum, ssi->gen_num, ssid);
00737                 return;
00738         }
00739 
00740         // Add the rule to the policy for this service set
00741         
00742         rule = rule_entry(patricia_get(&rules, strlen(name) + 1, name));
00743         if(rule == NULL) {
00744                 CLOG(LOG_ERR, "%s: Cannot find the rule %s", __func__, name);
00745                 return;
00746         }
00747         
00748     item = TAILQ_FIRST(&ssi->rules);
00749     while(item != NULL) {
00750         if (item->data == rule) {
00751             // already in list
00752             return;
00753         }
00754         item = TAILQ_NEXT(item, entries);
00755     }
00756 
00757     // it wasn't found so add it
00758     
00759         item = msp_shm_alloc(pdb_shm_handle, sizeof(list_item_t));        
00760         item->data = rule;
00761         
00762         TAILQ_INSERT_TAIL(&ssi->rules, item, entries);
00763         
00764         item = msp_shm_alloc(pdb_shm_handle, sizeof(list_item_t));        
00765         item->data = ssi;
00766         
00767         TAILQ_INSERT_TAIL(&rule->ssets, item, entries);
00768 }
00769 
00770 
00786 void
00787 remove_rule(char * name, uint16_t ssid, uint32_t gennum, uint32_t svcid)
00788 {
00789     msp_policy_db_params_t policy_db_params;
00790     ss_info_t * ssi;
00791     rule_t * rule;
00792     list_item_t * item;
00793         
00794     rule = rule_entry(patricia_get(&rules, strlen(name) + 1, name));
00795     
00796     if(rule == NULL) {
00797         CLOG(LOG_ERR, "%s: Cannot find the rule %s", __func__, name);
00798         return;
00799     }
00800     
00801         bzero(&policy_db_params, sizeof(msp_policy_db_params_t));
00802     
00803         // Get the current policy for the service set
00804         
00805         policy_db_params.handle = pdb_handle;
00806         policy_db_params.svc_set_id = ssid;
00807         policy_db_params.svc_id = svcid;
00808         policy_db_params.plugin_id = plugin_id;
00809         policy_db_params.policy_op = MSP_POLICY_DB_POLICY_GET;
00810         strlcpy(policy_db_params.plugin_name, PLUGIN_NAME,
00811                         sizeof(policy_db_params.plugin_name));
00812 
00813         if (msp_policy_db_op(&policy_db_params) != MSP_OK) {
00814                 CLOG(LOG_WARNING, "%s: No PDB configuration found", __func__);
00815                 return;
00816         }
00817         
00818         ssi = policy_db_params.op.get_params.policy;
00819         
00820         if(!ssi) {
00821                 CLOG(LOG_ERR, "%s: No policy found for service set", __func__);
00822                 return;
00823         }
00824         
00825         if(gennum != ssi->gen_num) {
00826                 CLOG(LOG_ERR, "%s: Generation number %d is out of sync with what is"
00827                                 "currently in the policy DB %d for this service set %d",
00828                                 __func__, gennum, ssi->gen_num, ssid);
00829                 return;
00830         }
00831         
00832         // Remove the rule from the rules list in ssi
00833         
00834     item = TAILQ_FIRST(&ssi->rules);
00835     while(item != NULL) {
00836         if (rule == item->data) {
00837                 TAILQ_REMOVE(&ssi->rules, item, entries);
00838                 msp_shm_free(pdb_shm_handle, item);
00839                 
00840                 // remove the reference of this ss in the ssets list of rule
00841                 
00842             item = TAILQ_FIRST(&rule->ssets);
00843             while(item != NULL) {
00844                 if(ssi == item->data) {
00845                         TAILQ_REMOVE(&rule->ssets, item, entries);
00846                         msp_shm_free(pdb_shm_handle, item);
00847                         break;
00848                 }
00849                 item = TAILQ_NEXT(item, entries);
00850             }
00851             break;
00852         }
00853         item = TAILQ_NEXT(item, entries);
00854     }
00855     
00856     if(TAILQ_FIRST(&ssi->rules) != NULL) // List is not empty
00857         return;
00858     
00859     // List of rules is empty, so let's remove this set's policy
00860         // Delete the current policy for the service set
00861     
00862         policy_db_params.policy_op = MSP_POLICY_DB_POLICY_DEL;
00863         policy_db_params.op.del_params.gen_num = gennum;
00864 
00865         if (msp_policy_db_op(&policy_db_params) != MSP_OK) {
00866                 CLOG(LOG_ERR, "%s: PDB Delete failed!", __func__);
00867                 return;
00868         }
00869         
00870     // delay the free of the policy in case someone did a GET op and is using it
00871         // make some random delay between 5-15 secs so there's not too many frees at
00872         // once (since it uses some locking in the shm pool) in case we're clearing
00873         // a lot
00874         
00875     if(evSetTimer(*ctx, free_policy, ssi, evAddTime(evNowTime(),
00876                 evConsTime(5 + (rand() % 11), 0)), evConsTime(0, 0), NULL)) {
00877 
00878         CLOG(LOG_EMERG, "%s: Failed to initialize a timer to free the policy "
00879             "(Error: %m)", __func__);
00880     }
00881 }
00882 
00883 
00890 void
00891 delete_serviceset(uint16_t ssid, uint32_t gennum, uint32_t svcid)
00892 {
00893     msp_policy_db_params_t policy_db_params;
00894     ss_info_t * ssi;
00895     rule_t * rule;
00896     list_item_t * item, * item2;
00897         
00898         bzero(&policy_db_params, sizeof(msp_policy_db_params_t));
00899     
00900         // Get the current policy for the service set
00901         
00902         policy_db_params.handle = pdb_handle;
00903         policy_db_params.svc_set_id = ssid;
00904         policy_db_params.svc_id = svcid;
00905         policy_db_params.plugin_id = plugin_id;
00906         policy_db_params.policy_op = MSP_POLICY_DB_POLICY_GET;
00907         strlcpy(policy_db_params.plugin_name, PLUGIN_NAME,
00908                         sizeof(policy_db_params.plugin_name));
00909 
00910         if (msp_policy_db_op(&policy_db_params) != MSP_OK) {
00911                 CLOG(LOG_WARNING, "%s: No PDB configuration found", __func__);
00912                 return;
00913         }
00914         
00915         ssi = policy_db_params.op.get_params.policy;
00916         
00917         if(!ssi) {
00918                 CLOG(LOG_ERR, "%s: No policy for service set to delete", __func__);
00919                 return;
00920         }
00921         
00922         if(gennum != ssi->gen_num) {
00923                 CLOG(LOG_ERR, "%s: Generation number %d is out of sync with what is"
00924                                 "currently in the policy DB %d for this service set %d",
00925                                 __func__, gennum, ssi->gen_num, ssid);
00926                 return;
00927         }
00928         
00929         // delete references from rules to this service set
00930         // we delete the reference to the rules from this sset in the delayed delete
00931         
00932     while((item = TAILQ_FIRST(&ssi->rules)) != NULL) {
00933         rule = item->data;
00934         
00935         item2 = TAILQ_FIRST(&rule->ssets);
00936         while(item2 != NULL) {
00937                 if(ssi == item2->data) {
00938                 TAILQ_REMOVE(&rule->ssets, item2, entries);
00939                 msp_shm_free(pdb_shm_handle, item2);
00940                         break;
00941                 }
00942                 item2 = TAILQ_NEXT(item2, entries);
00943         }
00944         item = TAILQ_NEXT(item, entries);
00945     }
00946         
00947         // Delete the current policy for the service set
00948         
00949         policy_db_params.policy_op = MSP_POLICY_DB_POLICY_DEL;
00950         policy_db_params.op.del_params.gen_num = gennum;
00951 
00952         if (msp_policy_db_op(&policy_db_params) != MSP_OK) {
00953                 CLOG(LOG_ERR, "%s: PDB Delete failed!", __func__);
00954                 return;
00955         }
00956         
00957         
00958     // delay the free of the policy in case someone did a GET op and is using it
00959         // make some random delay between 5-15 secs so there's not too many frees at
00960         // once (since it uses some locking in the shm pool) in case we're clearing
00961         // a lot
00962         
00963     if(evSetTimer(*ctx, free_policy, ssi, evAddTime(evNowTime(),
00964                 evConsTime(5 + (rand() % 11), 0)), evConsTime(0, 0), NULL)) {
00965 
00966         CLOG(LOG_EMERG, "%s: Failed to initialize a timer to free the policy "
00967             "(Error: %m)", __func__);
00968     }
00969 }
00970 
00971 
00993 int
00994 get_monitored_rule_info(uint16_t ssid,
00995                                 uint32_t svcid,
00996                                 in_addr_t address,
00997                                 uint32_t * rate,
00998                                 uint32_t * redirect_addr)
00999 {
01000     msp_policy_db_params_t policy_db_params;
01001         rnode_t * rn;
01002     prefix_t * prefix;
01003     ss_info_t * ssi;
01004 
01005         bzero(&policy_db_params, sizeof(msp_policy_db_params_t));
01006         
01007         // Get the current policy for the service set
01008         
01009         policy_db_params.handle = pdb_handle;
01010         policy_db_params.svc_set_id = ssid;
01011         policy_db_params.svc_id = svcid;
01012         policy_db_params.plugin_id = plugin_id;
01013         policy_db_params.policy_op = MSP_POLICY_DB_POLICY_GET;
01014         strlcpy(policy_db_params.plugin_name, PLUGIN_NAME,
01015                         sizeof(policy_db_params.plugin_name));
01016 
01017         if (msp_policy_db_op(&policy_db_params) != MSP_OK) {
01018                 DLOG(LOG_ERR, "%s: PDB Get failed!", __func__);
01019                 return -1;
01020         }
01021         
01022         ssi = policy_db_params.op.get_params.policy;
01023         
01024         if(!ssi)
01025                 return -1;
01026         
01027         RLOCK(&ssi->prefixes_lock); // hold while using any prefix in prefixes
01028         
01029     rn = radix_lookup(&ssi->prefixes, (uint8_t *)&address);
01030     
01031     if(rn == NULL) {
01032         return -1;
01033     }
01034 
01035     prefix = (prefix_t *)((uint8_t *)rn - offsetof(prefix_t, rnode));
01036 
01037         RLOCK(&prefix->rule->lock);
01038         
01039     if(rate)
01040         *rate = prefix->rule->rate;
01041     
01042     if(redirect_addr)
01043         *redirect_addr = prefix->rule->redirect;
01044     
01045     RUNLOCK(&prefix->rule->lock);
01046     
01047     RUNLOCK(&ssi->prefixes_lock);
01048     
01049     return 0;
01050 }
01051 

2007-2009 Juniper Networks, Inc. All rights reserved. The information contained herein is confidential information of Juniper Networks, Inc., and may not be used, disclosed, distributed, modified, or copied without the prior written consent of Juniper Networks, Inc. in an express license. This information is subject to change by Juniper Networks, Inc. Juniper Networks, the Juniper Networks logo, and JUNOS are registered trademarks of Juniper Networks, Inc. in the United States and other countries. All other trademarks, service marks, registered trademarks, or registered service marks are the property of their respective owners.
Generated on Sun May 30 20:27:09 2010 for SDK Your Net Corporation Monitube2 IPTV Monitoring Example: monitube2-plugin 1.0 by Doxygen 1.5.1