psd_config.c

Go to the documentation of this file.
00001 /*
00002  * $Id: psd_config.c 346460 2009-11-14 05:06:47Z ssiano $
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) 2007-2008, Juniper Networks, Inc.
00011  * All rights reserved.
00012  */
00013 
00014 
00022 #include <sync/common.h>
00023 #include <sync/psd_ipc.h>
00024 #include <ddl/dax.h>
00025 #include "psd_server.h"
00026 #include "psd_config.h"
00027 
00028 #include PS_OUT_H
00029 
00030 /*** Constants ***/
00031 
00032 #define EMPTY -3               
00033 #define DEFAULT_ROUTE_METRIC 5 
00034 #define DEFAULT_ROUTE_PREF   5 
00035 
00036 /*** Data structures: ***/
00037 
00038 
00039 static patroot root_policy; 
00040 
00041 
00042 /*** STATIC/INTERNAL Functions ***/
00043 
00044 
00049 PATNODE_TO_STRUCT(policy_entry, psd_policy_t, node)
00050 
00051 
00052 
00059 static void
00060 delete_policy(psd_policy_t *policy)
00061 {
00062     psd_policy_route_t *route, *route_tmp;
00063 
00064     //Free filter policy data.
00065     free(policy->filter);
00066 
00067     //Free the list of route policy data.
00068     route = policy->route;
00069     while(route) {
00070         route_tmp = route->next;  // Save pointer to next route.
00071         free(route);  // Free current route.
00072         route = route_tmp;  // Move to next route.
00073     }
00074 
00075     //Remove policy from patricia tree.
00076     if (!patricia_delete(&root_policy, &policy->node)) {
00077         junos_trace(PSD_TRACEFLAG_NORMAL, 
00078                 "%s: Delete policy FAILED!", __func__);
00079     }
00080 }
00081 
00082 
00086 static void
00087 clear_config_policy(void)
00088 {
00089     psd_policy_t *policy = NULL;
00090 
00091     while((policy = first_policy()) != NULL) {
00092         delete_policy(policy);  // Remove policy from configuration
00093         free(policy);  // Free policy
00094     }
00095 }
00096 
00097 
00110 static int
00111 config_read_route(ddl_handle_t *policy_op, psd_policy_t *policy)
00112 {
00113     ddl_handle_t *route_list_op = NULL;
00114     ddl_handle_t *route_op = NULL;
00115     psd_policy_route_t *route = NULL;
00116     psd_policy_route_t *route_end = NULL;
00117     int val_af; // we assume IPv4 is always returned
00118     struct in_addr addr;
00119     int status = SUCCESS;
00120 
00121     policy->route = NULL;
00122 
00123     if(!dax_get_object_by_aid(policy_op, DDLAID_SYNC_PS_POLICY_ROUTE,          
00124             &route_list_op, FALSE)) {
00125         return EMPTY;  // No route configuration, no complain.
00126     }
00127 
00128     while(dax_visit_container(route_list_op, &route_op)) {
00129 
00130         // Create route data.
00131         route = calloc(1, sizeof(psd_policy_route_t));
00132         INSIST(route != NULL);
00133 
00134         // Read route address, support IPv4 only for now.
00135         if(!dax_get_ipprefix_by_aid(route_op, ROUTE_ADDRESS, &val_af,
00136                 &(route->route_data.route_addr), 4,
00137                 &(route->route_data.route_addr_prefix))) {
00138             dax_error(route_op, "Read route address FAILED!");
00139             status = EFAIL;
00140             free(route);
00141             break;
00142         }
00143 
00144         if(!dax_get_uint_by_aid(route_op, METRICS,
00145                 &(route->route_data.metrics))) {
00146             route->route_data.metrics = DEFAULT_ROUTE_METRIC;
00147         }
00148         if(!dax_get_uint_by_aid(route_op, PREFERENCES,
00149                 &(route->route_data.preferences))) {
00150             route->route_data.preferences = DEFAULT_ROUTE_PREF;
00151         }
00152         if(!dax_get_ubyte_by_aid(route_op, NH_TYPE,
00153                 &(route->route_data.nh_type))) {
00154             dax_error(route_op, "Read next-hop address FAILED!");
00155             status = EFAIL;
00156             free(route);
00157             break;
00158         }
00159 
00160         addr.s_addr = route->route_data.route_addr;
00161         
00162         junos_trace(PSD_TRACEFLAG_CONFIG,
00163                 "%s: route address: %s/%d", __func__,
00164                 inet_ntoa(addr), route->route_data.route_addr_prefix);
00165                 
00166         junos_trace(PSD_TRACEFLAG_CONFIG, "%s: m: %d, p: %d",
00167                 __func__, route->route_data.metrics,
00168                 route->route_data.preferences);
00169                 
00170         junos_trace(PSD_TRACEFLAG_CONFIG, "%s: next-hop type: %d",
00171                 __func__, route->route_data.nh_type);
00172 
00173         // if we have a nh address, type is unicast
00174         dax_get_ipaddr_by_aid(route_op, NH_ADDRESS,
00175                 &val_af, &(route->route_data.nh_addr), 4);
00176 
00177         if(route->route_data.nh_type == PSD_NH_TYPE_UNICAST) {
00178             addr.s_addr = route->route_data.nh_addr;
00179             junos_trace(PSD_TRACEFLAG_CONFIG, "%s: next-hop address: %s",
00180                 __func__, inet_ntoa(addr));
00181         }
00182 
00183         // Copy interface name and address family to route data.
00184         strcpy(route->route_data.ifname, policy->ifname);
00185         route->route_data.af = policy->af;
00186         route->next = NULL;
00187 
00188         if(policy->route) {
00189             // Add route data to the end of the list.
00190             route_end->next = route;
00191         } else {
00192             // This is the first route data in the list.
00193             policy->route = route;
00194         }
00195 
00196         // Set pointer to the last route in the list.
00197         route_end = route;
00198     }
00199     // note: if status is EFAIL, then route list will be free later
00200 
00201     dax_release_object(&route_list_op);
00202     dax_release_object(&route_op);
00203     return status;
00204 }
00205 
00206 
00219 static int
00220 config_read_filter(ddl_handle_t *policy_op, psd_policy_t *policy)
00221 {
00222     ddl_handle_t *filter_op = NULL;
00223     psd_policy_filter_t *filter = NULL;
00224     int status = SUCCESS;
00225 
00226     policy->filter = NULL;
00227     if(!dax_get_object_by_aid(policy_op, DDLAID_SYNC_PS_POLICY_FILTER,          
00228             &filter_op, FALSE)) {
00229         return EMPTY;  // No filter configuration, no complain.
00230     }
00231 
00232     // Create filter data.
00233     filter = calloc(1, sizeof(psd_policy_filter_t));
00234     INSIST(filter != NULL);
00235 
00236     // Read input filter and output filter.
00237     dax_get_stringr_by_aid(filter_op, POLICY_INPUT_FILTER,
00238             filter->filter_data.input_filter, MAX_FILTER_NAME_LEN);
00239     dax_get_stringr_by_aid(filter_op, POLICY_OUTPUT_FILTER, 
00240             filter->filter_data.output_filter, MAX_FILTER_NAME_LEN);
00241 
00242     junos_trace(PSD_TRACEFLAG_CONFIG,
00243             "%s: Input filter: %s, Output filter: %s", __func__,
00244             filter->filter_data.input_filter,
00245             filter->filter_data.output_filter);
00246 
00247     // At least one filter must be specified
00248     if(filter->filter_data.input_filter[0] ||
00249             filter->filter_data.output_filter[0]) {
00250         
00251         // Copy interface name and address family to filter data.
00252         strcpy(filter->filter_data.ifname, policy->ifname);
00253         filter->filter_data.af = policy->af;
00254         // Set filter pointer in policy data.
00255         policy->filter = filter;
00256     } else {
00257         free(filter);
00258         policy->filter = NULL;
00259         status = EFAIL;
00260     }
00261     
00262     dax_release_object(&filter_op);
00263     return status;
00264 }
00265 
00266 
00267 /*** GLOBAL/EXTERNAL Functions ***/
00268 
00269 
00274 void
00275 init_config(void)
00276 {
00277     patricia_root_init(&root_policy, FALSE, MAX_POLICY_NAME_LEN + 1, 0);
00278                       // root, is key ptr, key size, key offset
00279 }
00280 
00281 
00289 psd_policy_t *
00290 first_policy(void)
00291 {
00292     return policy_entry(patricia_find_next(&root_policy, NULL));
00293 }
00294 
00306 psd_policy_t *
00307 next_policy(psd_policy_t *policy)
00308 {
00309     return policy_entry(patricia_find_next(&root_policy,
00310             (policy ? &(policy->node) : NULL)));
00311 }
00312 
00327 int
00328 psd_config_read(int check)
00329 {
00330     ddl_handle_t *policy_op = NULL;
00331     ddl_handle_t *policy_list_op = NULL;
00332     const char   *psd_policy[] =    {DDLNAME_SYNC,
00333                                      DDLNAME_SYNC_PS,
00334                                      DDLNAME_SYNC_PS_POLICY, NULL};
00335     psd_policy_t *policy = NULL;
00336     psd_policy_route_t *route = NULL;
00337     psd_policy_route_t *route_tmp = NULL;
00338     int status = 0;
00339 
00340     junos_trace(PSD_TRACEFLAG_CONFIG,
00341             "%s: Load configuration, check %d",
00342             __func__, check);
00343 
00344     // Read policy configuration, get the pointer the policy list.
00345     //                               (FALSE flag = regardless of if was changed)
00346     if(!dax_get_object_by_path(NULL, psd_policy, &policy_list_op, FALSE)) {
00347         
00348         // clear stored config data because we have no configure data
00349         clear_config_policy();
00350         junos_trace(PSD_TRACEFLAG_CONFIG,
00351                 "%s: Nothing to configure", __func__);
00352         return SUCCESS;  // No policy, no complain.
00353     }
00354 
00355         // Load policy only if something changed.
00356     if(dax_is_changed(policy_list_op)) {
00357 
00358         // Clear policy configuration, get ready for new data.
00359         clear_config_policy();
00360 
00361         // Get pointer to policy object.
00362         while(dax_visit_container(policy_list_op, &policy_op)) {
00363 
00364             // Create and clear policy data.
00365             policy = calloc(1, sizeof(psd_policy_t));
00366             INSIST(policy != NULL);
00367 
00368             // Initialize pointers.
00369             policy->filter = NULL;
00370             policy->route = NULL;
00371 
00372             // Read policy name.
00373             if(!dax_get_stringr_by_aid(policy_op, POLICY_NAME,
00374                     policy->policy_name, sizeof(policy->policy_name))) {
00375                 dax_error(policy_op, "Read policy name FAILED!");
00376                 goto error;
00377             }
00378 
00379             // Read interface name.
00380             if(!dax_get_stringr_by_aid(policy_op, POLICY_INTERFACE_NAME,
00381                     policy->ifname, sizeof(policy->ifname))) {
00382                 dax_error(policy_op, "Read interface name FAILED!");
00383                 goto error;
00384             }
00385 
00386             // Read address family.
00387             if(!dax_get_ubyte_by_aid(policy_op, POLICY_ADDRESS_FAMILY,
00388                     &(policy->af))) {
00389                 dax_error(policy_op, "Read address family FAILED!");
00390                 goto error;
00391             }
00392 
00393             if((status = config_read_filter(policy_op, policy)) == EFAIL) {
00394                 dax_error(policy_op, "Read filter object FAILED!");
00395                 goto error;
00396                 
00397             } else if(status == EMPTY) { // no filter
00398                 if((status = config_read_route(policy_op, policy)) == EFAIL) {
00399                     dax_error(policy_op, "Read list of route objects FAILED!");
00400                     goto error;
00401                 } else if(status == EMPTY) { // no routes (and no filter)
00402                     // empty policy
00403                     dax_error(policy_op,
00404                         "Policy contains no filter and no route(s)!");
00405                     goto error;
00406                 }
00407                 
00408             } else {
00409                 if((status = config_read_route(policy_op, policy)) == EFAIL) {
00410                     dax_error(policy_op, "Read list of route objects FAILED!");
00411                     goto error;
00412                 }                
00413             }
00414             
00415 
00416             // Add policy data to patricia tree.
00417             patricia_node_init_length(&policy->node,
00418                     strlen(policy->policy_name) + 1);
00419 
00420             if(!patricia_add(&root_policy, &policy->node)) {
00421                 dax_error(policy_op, 
00422                     "Adding policy to loaded configuration FAILED!");
00423                goto error;
00424             }
00425         }
00426         junos_trace(PSD_TRACEFLAG_CONFIG,
00427                 "%s: Load configuration DONE.", __func__);
00428     } else {
00429         junos_trace(PSD_TRACEFLAG_CONFIG,
00430                 "%s: No configuration change", __func__);
00431     }
00432 
00433     dax_release_object(&policy_op);
00434     dax_release_object(&policy_list_op);
00435     
00436     if(!check) {
00437         notify_all_clients(); // Tell PED to update
00438     }
00439     return SUCCESS;
00440 
00441 error:
00442     if(policy) {
00443         if(policy->filter) {
00444             free(policy->filter);
00445         }
00446         route = policy->route;
00447         while(route) {
00448             route_tmp = route->next;
00449             free(route);
00450             route = route_tmp;
00451         }
00452         free(policy);
00453     }
00454     dax_release_object(&policy_op);
00455     dax_release_object(&policy_list_op);
00456     return -1;
00457 }

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:07 2010 for SDK Your Net Corporation Policy Manager Example: Policy Server Daemon 1.0 by Doxygen 1.5.1