passthru_main.c

Go to the documentation of this file.
00001 /*
00002  * $Id: passthru_main.c 358766 2010-01-20 16:37:38Z jamesk $
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 
00020 /* The Application and This Plug-in's Documentation: */
00021 
00120 #include <stdlib.h>
00121 #include <string.h>
00122 #include <sys/types.h>
00123 #include <jnx/aux_types.h>
00124 #include <sys/socket.h>
00125 #include <netinet/in.h>
00126 #include <arpa/inet.h>
00127 #include <netinet/in_systm.h>
00128 #include <netinet/ip.h>
00129 #include <netinet/ip_icmp.h>
00130 #include <jnx/logging.h>
00131 #include <jnx/msp_trace.h>
00132 #include <jnx/junos_kcom.h>
00133 #include <jnx/mpsdk.h>
00134 #include <sys/jnx/jbuf.h>
00135 #include <jnx/msp_objcache.h>
00136 #include <jnx/msp_policy_db.h>
00137 #include <jnx/multi-svcs/msvcs_plugin.h>
00138 #include <jnx/multi-svcs/msvcs_state.h>
00139 #include <jnx/multi-svcs/msvcs_events.h>
00140 #include <jnx/multi-svcs/msvcs_flow.h>
00141 #include <jnx/multi-svcs/msvcs_session.h>
00142 #include <jnx/junos_kcom_mpsdk_cfg.h>
00143 #include <jnx/msp_pkt_utils.h>
00144 
00145 /*** Constants ***/
00146 
00147 // PROCESSING MODES:
00148 
00154 #define SESSION_BASED_MODE     1
00155 
00160 #define PACKET_BASED_MODE      2
00161 
00165 #define PROCESSING_MODE SESSION_BASED_MODE
00166 
00170 #define WITH_POLICY_DATABASE   1
00171 
00175 #define NO_POLICY_DATABASE     2
00176 
00180 #define CONFIG_MODE NO_POLICY_DATABASE
00181 
00185 #define PASSTHRU_PLUGIN_NAME "passthru-plugin"
00186 
00190 #define PASSTHRU_PLUGIN_ID 0
00191 
00195 #define SESSION_DESC_LEN (INET_ADDRSTRLEN + 4 + INET_ADDRSTRLEN + 1)
00196 
00200 #define CLOG(_level, _fmt...)   \
00201     logging((_level), "PASSTHRU PLUG-IN: " _fmt)
00202 
00206 #define DLOG(_level, _fmt...)   \
00207     msp_log((_level), "PASSTHRU PLUG-IN: " _fmt)
00208 
00209 // protocol strings
00210 const char * tcp_str = "TCP";     
00211 const char * udp_str = "UDP";     
00212 const char * icmp_str = "ICMP";   
00213 
00214 // PIC redundancy-state strings for KCOM_IFDEV_REDUNDANCY_STATE_* values
00215 const char * waiting_state = "waiting for primary"; 
00216 const char * primary_state = "primary active";      
00217 const char * secondary_state = "secondary active";  
00218 const char * none_state = "none active";            
00219 
00220 // PIC redundancy operations for KCOM_IFDEV_REDUNDANCY_CMD_* values
00221 const char * no_op = "none";        
00222 const char * switch_op = "switch";  
00223 const char * revert_op = "revert";  
00224 
00225 
00226 /*** Data Structures ***/
00227 
00228 
00232 static int plugin_id;
00233 
00237 static evContext * ctx;
00238 
00239 #if CONFIG_MODE == WITH_POLICY_DATABASE
00240 
00243 static msp_policy_db_handle_t pdb_handle;
00244 
00245 #endif
00246 
00250 static msp_oc_handle_t soc_handle;
00251 
00252 
00253 /*** STATIC/INTERNAL Functions ***/
00254 
00255 
00270 static status_t
00271 pullup_bytes(struct jbuf ** pkt_buf, uint16_t num_bytes)
00272 {
00273     struct jbuf * tmp_buf;
00274 
00275     if(jbuf_particle_get_data_length(*pkt_buf) < num_bytes) {
00276         tmp_buf = jbuf_pullup((*pkt_buf), num_bytes);
00277 
00278         if(!tmp_buf) { // check in case it failed
00279             DLOG(LOG_ERR, "%s: jbuf_pullup() of %d failed on jbuf of length %d",
00280                     __func__, num_bytes, jbuf_total_len(*pkt_buf));
00281             return EFAIL;
00282         }
00283 
00284         *pkt_buf = tmp_buf;
00285     }
00286     return SUCCESS;
00287 }
00288 
00289 
00301 static int
00302 passthru_data_hdlr(msvcs_data_context_t * md_ctx,
00303                    msvcs_data_event_t ev)
00304 {
00305     msvcs_pub_data_req_t * req;
00306     msp_objcache_params_t ocp;
00307     struct jbuf * jb;
00308     struct ip * ip_hdr;
00309     const char * protocol;
00310     char tmp1[INET_ADDRSTRLEN];
00311     char tmp2[INET_ADDRSTRLEN];
00312     char * forward, * reverse, * desc;
00313     int rc, cpu = msvcs_state_get_cpuid();
00314 
00315     DLOG(LOG_INFO, "%s: Handling data event for plug-in %d from CPU %d.",
00316             __func__, plugin_id, cpu);
00317 
00318     switch (ev) {
00319     case MSVCS_DATA_EV_SM_INIT:
00320         
00321         // Should only get this once, and first
00322 
00323         DLOG(LOG_INFO, "%s: Initialization of shared memory event", __func__);
00324 
00325         bzero(&ocp, sizeof(ocp));
00326         ocp.oc_shm = md_ctx->sc_shm; // use the global SHM arena handle
00327         strlcpy(ocp.oc_name, PASSTHRU_PLUGIN_NAME "OC", sizeof(ocp.oc_name));
00328         ocp.oc_size = SESSION_DESC_LEN;
00329         
00330         rc = msp_objcache_create(&ocp);
00331 
00332         if(rc) {
00333             DLOG(LOG_ERR, "%s: Failed to initialize an object cache", __func__);
00334             return rc;
00335         }
00336 
00337         // Save the OC handle
00338         soc_handle = ocp.oc;
00339 
00340         break;
00341 
00342     case MSVCS_DATA_EV_INIT:
00343         
00344         // Should only get this once, and second
00345 
00346         DLOG(LOG_INFO, "%s: General initialization event", __func__);
00347 
00348         break;
00349 
00350     case MSVCS_DATA_EV_FIRST_PKT_PROC:
00351         
00352 #if PROCESSING_MODE == SESSION_BASED_MODE
00353         // First event received only once for every session
00354         if (md_ctx->sc_session) {
00355             DLOG(LOG_INFO, "%s: Received the first packet of a session",
00356                     __func__);
00357         } else {
00358             DLOG(LOG_EMERG, "%s: Received a packet without a session in "
00359                     "session-based mode", __func__);
00360             return MSVCS_ST_PKT_DISCARD;
00361         }
00362 #elif PROCESSING_MODE == PACKET_BASED_MODE
00363         if (md_ctx->sc_session) {
00364             DLOG(LOG_EMERG, "%s: Received the first packet of a session in "
00365                     "packet-based mode", __func__);
00366             return MSVCS_ST_PKT_DISCARD;
00367         } else {
00368             // plug-in was setup to be packet based, not session based
00369             DLOG(LOG_INFO, "%s: Received a packet in packet-based mode",
00370                     __func__);
00371             return MSVCS_ST_PKT_FORWARD; // don't do string description stuff
00372         }
00373 #endif
00374 
00375         jb = (struct jbuf *)md_ctx->sc_pkt;
00376 
00377         if(pullup_bytes(&jb, sizeof(struct ip))) {
00378             DLOG(LOG_ERR, "%s: Failed to pullup IP header bytes, dropping "
00379                     "packet", __func__);
00380             return MSVCS_ST_PKT_DISCARD;
00381         }
00382         
00383         // safe typecast to an IP header
00384         ip_hdr = jbuf_to_d(jb, struct ip *);
00385         
00386         // store description strings as the session metadata 
00387 
00388         inet_ntop(AF_INET, &ip_hdr->ip_src, tmp1, sizeof(tmp1));
00389         inet_ntop(AF_INET, &ip_hdr->ip_dst, tmp2, sizeof(tmp2));
00390         
00391         forward = msp_objcache_alloc(soc_handle, cpu, md_ctx->sc_sset_id);
00392         reverse = msp_objcache_alloc(soc_handle, cpu, md_ctx->sc_sset_id);
00393 
00394         if(md_ctx->sc_flags & MSVCS_CTX_FLAGS_DIR_REVERSE) {
00395             sprintf(reverse, "%s -> %s", tmp1, tmp2); // for the current packet
00396             sprintf(forward, "%s -> %s", tmp2, tmp1);
00397         } else {
00398             sprintf(forward, "%s -> %s", tmp1, tmp2); // for the current packet
00399             sprintf(reverse, "%s -> %s", tmp2, tmp1);
00400         }
00401 
00402         // save a simple textual description of the flow
00403         msvcs_session_set_ext_handle((msvcs_session_t *)md_ctx->sc_session,
00404                 (uint8_t)plugin_id, forward, reverse);
00405 
00406         // fall through (no break or return)
00407 
00408     case MSVCS_DATA_EV_PKT_PROC:
00409         
00410 #if PROCESSING_MODE == PACKET_BASED_MODE
00411         
00412         // All packets should arrive as MSVCS_DATA_EV_FIRST_PKT_PROC
00413         
00414         DLOG(LOG_NOTICE, "%s: Received packet in packet-based mode, but event "
00415                 "type is unrecognized for this mode (MSVCS_DATA_EV_PKT_PROC)",
00416                 __func__);            
00417 
00418         return MSVCS_ST_PKT_FORWARD; // don't do string description stuff
00419 #endif
00420         
00421         if (!md_ctx->sc_session) {
00422             DLOG(LOG_EMERG, "%s: Received packet without a session in "
00423                     "session-based mode", __func__);
00424             return MSVCS_ST_PKT_DISCARD;
00425         }
00426         
00427         // received for all packets in a session following the first one
00428 
00429         jb = (struct jbuf *)md_ctx->sc_pkt;
00430 
00431         if(pullup_bytes(&jb, sizeof(struct ip))) {
00432             DLOG(LOG_ERR, "%s: Failed to pullup IP header bytes, dropping "
00433                     "packet", __func__);
00434             return MSVCS_ST_PKT_DISCARD;
00435         }
00436 
00437         // safe typecast to an IP header
00438         ip_hdr = jbuf_to_d(jb, struct ip *);
00439 
00440         // find a string matching the protocol
00441         switch(ip_hdr->ip_p) {
00442         case IPPROTO_TCP:
00443             protocol = tcp_str;
00444             break;
00445         case IPPROTO_UDP:
00446             protocol = udp_str;
00447             break;
00448         case IPPROTO_ICMP:
00449             protocol = icmp_str;
00450             break;
00451         default:
00452             snprintf(tmp1, sizeof(tmp1), "%d", (int)ip_hdr->ip_p);
00453             protocol = tmp1;
00454             break;
00455         }
00456 
00457         // find the string stored in the session context describing what we want
00458         if(md_ctx->sc_flags & MSVCS_CTX_FLAGS_DIR_FORWARD) {
00459             msvcs_session_get_ext_handle((msvcs_session_t *)md_ctx->sc_session,
00460                     (uint8_t)plugin_id, (void **)&desc, NULL);
00461         } else if(md_ctx->sc_flags & MSVCS_CTX_FLAGS_DIR_REVERSE) {
00462             msvcs_session_get_ext_handle((msvcs_session_t *)md_ctx->sc_session,
00463                     (uint8_t)plugin_id, NULL, (void **)&desc);
00464         } else {
00465             // should never happen
00466             DLOG(LOG_ALERT, "%s: Direction of packet is not defined.");
00467         }
00468 
00469         if(!desc) {
00470             DLOG(LOG_ERR, "%s: Could not retrieve session context", __func__);
00471         } else {
00472             DLOG(LOG_INFO, "%s: %s packet of SS: %d, Direction: %s, %s",
00473                 __func__, protocol, md_ctx->sc_sset_id,
00474                 ((md_ctx->sc_flags & MSVCS_CTX_FLAGS_DIR_FORWARD) ?
00475                         "forward" : "reverse"),
00476                 desc);
00477         }
00478         
00479         if(jb != md_ctx->sc_pkt) {
00480             // if a new jbuf was returned during any jbuf manipulations, then
00481             // we can't return forward. We hold the old jbuf (which is eaten by 
00482             // jbuf APIs anyway) and we inject the new jbuf
00483             // Note this cannot be done on "first" packets
00484             
00485             // Having only done a pullup this is usually not supposed to happen,
00486             // but just in case...
00487             
00488             msp_reinject_packet((msvcs_session_t *)md_ctx->sc_session, jb);
00489             
00490             return MSVCS_ST_PKT_HOLD;
00491         }
00492 
00493         return MSVCS_ST_PKT_FORWARD;
00494 
00495     case MSVCS_DATA_EV_SESSION_OPEN:
00496 
00497         // received after all plug-ins have decided to forward the first packet
00498         // of a session
00499         
00500         // print out forward-based flow info only
00501 
00502         msvcs_session_get_ext_handle((msvcs_session_t *)md_ctx->sc_session,
00503                 (uint8_t)plugin_id, (void **)&desc, NULL);
00504 
00505         if(!desc) {
00506             DLOG(LOG_ERR, "%s: Could not retrieve session context", __func__);
00507         } else {
00508             DLOG(LOG_INFO, "%s: Session opened for %s", __func__, desc);
00509         }
00510 
00511         break;
00512 
00513     case MSVCS_DATA_EV_SESSION_CLOSE:
00514         
00515         // received when an existing session (OPEN rcv'd previously) times out
00516 
00517         DLOG(LOG_INFO, "%s: Session closed", __func__);
00518 
00519         // print out forward-based flow info only
00520 
00521         msvcs_session_get_ext_handle((msvcs_session_t *)md_ctx->sc_session,
00522                 (uint8_t)plugin_id, (void **)&desc, NULL);
00523 
00524         if(!desc) {
00525             DLOG(LOG_ERR, "%s: Could not retrieve session context", __func__);
00526         } else {
00527             DLOG(LOG_INFO, "%s: Session closed for %s", __func__, desc);
00528         }
00529 
00530         break;
00531 
00532     case MSVCS_DATA_EV_SESSION_DESTROY:
00533         
00534         // All plug-ins have been notified about the CLOSE or some plug-in 
00535         // dropped the first packet of a session, so no open/close was received
00536 
00537         DLOG(LOG_INFO, "%s: Session destroyed", __func__);
00538 
00539         // Get and free attached session context containing the textual desc
00540         msvcs_session_get_ext_handle((msvcs_session_t *)md_ctx->sc_session,
00541                 (uint8_t)plugin_id, (void **)&forward, (void **)&reverse);
00542 
00543         if(forward) {
00544             msp_objcache_free(soc_handle, forward, cpu, md_ctx->sc_sset_id);
00545         } else {
00546             DLOG(LOG_ERR, "%s: Could not retrieve forward session context",
00547                     __func__);
00548         }
00549 
00550         if(reverse) {
00551             msp_objcache_free(soc_handle, reverse, cpu, md_ctx->sc_sset_id);
00552         } else {
00553             DLOG(LOG_ERR, "%s: Could not retrieve reverse session context",
00554                     __func__);
00555         }
00556         
00557         break;
00558 
00559     case MSVCS_DATA_EV_REQ_PUB_DATA:
00560 
00561         req = md_ctx->plugin_data;
00562 
00563         DLOG(LOG_INFO, "%s: Requesting public data %d", __func__, req->data_id);
00564 
00565         // we do not expect this event; no one would be requesting data from us
00566         req->err = -1; // we do not have any public data to give
00567 
00568         break;
00569 
00570     default:
00571 
00572         DLOG(LOG_ERR, "%s: Received an unhandled data event %X", __func__, ev);
00573     }
00574 
00575     return MSVCS_ST_OK;
00576 }
00577 
00578 
00590 static int
00591 passthru_ctrl_hdlr(msvcs_control_context_t * mc_ctx,
00592                    msvcs_control_event_t ev)
00593 {
00594 #if CONFIG_MODE == WITH_POLICY_DATABASE
00595     msp_policy_db_params_t policy_db_params;
00596 #endif
00597     
00598     junos_kcom_gencfg_t * jkg;
00599     msvcs_ha_info_hdr_t * ha_info;
00600     kcom_ifdev_redundancy_info_t * ri;
00601     const char * op, * state;
00602     char tmp1[32], tmp2[32];
00603 
00604     CLOG(LOG_INFO, "%s: Handling control event for plug-in %d from CPU %d.",
00605             __func__, plugin_id, msvcs_state_get_cpuid());
00606 
00607     switch (ev) {
00608     case MSVCS_CONTROL_EV_INIT:
00609 
00610         CLOG(LOG_INFO, "%s: Initialization Event...", __func__);
00611 
00612         // do initialization here
00613 
00614         ctx = mc_ctx->scc_ev_ctxt;
00615         
00616 #if CONFIG_MODE == WITH_POLICY_DATABASE
00617         
00618         pdb_handle = mc_ctx->policy_db_handle;
00619 
00620         // Put some dummy data into the policy database
00621         bzero(&policy_db_params, sizeof(msp_policy_db_params_t));
00622         policy_db_params.handle = pdb_handle;
00623         policy_db_params.svc_set_id = 1;
00624         policy_db_params.svc_id = MSP_SVC_ID_SERVICES;
00625         policy_db_params.plugin_id = plugin_id;
00626         policy_db_params.policy_op = MSP_POLICY_DB_POLICY_ADD;
00627         strlcpy(policy_db_params.plugin_name, PASSTHRU_PLUGIN_NAME,
00628                 sizeof(policy_db_params.plugin_name));
00629 
00630         // Add params
00631         policy_db_params.op.add_params.gen_num = 0;
00632 
00633 #if PROCESSING_MODE == PACKET_BASED_MODE
00634         // Enable this to make the plugin a packet-based processing plugin
00635         // where no session is created for packets of this service set
00636         policy_db_params.op.add_params.policy_flags = 
00637             MSP_POLICY_FLAGS_SSET_PACKET;
00638 #endif
00639 
00640         policy_db_params.op.add_params.policy =
00641             msp_shm_alloc(mc_ctx->policy_shm_handle,
00642                 strlen(PASSTHRU_PLUGIN_NAME) + 1);
00643         // put the plug-in's name into PDB
00644         if(!policy_db_params.op.add_params.policy) {
00645             CLOG(LOG_ERR, "%s: Cannot allocate into policy SHM...", __func__);
00646             break;
00647         }
00648         strcpy(policy_db_params.op.add_params.policy, PASSTHRU_PLUGIN_NAME);
00649 
00650         if (msp_policy_db_op(&policy_db_params) != MSP_OK) {
00651             CLOG(LOG_ERR, "%s: Policy DB Add failed!", __func__);
00652         }
00653         
00654 #endif
00655 
00656         break;
00657 
00658     case MSVCS_CONTROL_EV_CFG_BLOB:
00659 
00660         CLOG(LOG_INFO, "%s: Configuration Event", __func__);
00661 
00662         // we do not expect this event as their is no RE-SDK (mgmt) component
00663         // normally we populate the policy database with application data
00664         // inserted into the blob from the mgmt component
00665         jkg = (junos_kcom_gencfg_t *)mc_ctx->plugin_data;
00666 
00667         if(!jkg) {
00668             CLOG(LOG_ERR, "%s: Malformed control event", __func__);
00669             break;
00670         }
00671 
00672         CLOG(LOG_INFO, "%s: received the GENCFG operation %d with key of "
00673                 "size %d and blob of size %d. It was sent to %d MS PIC peers.",
00674                 __func__, jkg->opcode, jkg->key.size, jkg->blob.size,
00675                 jkg->peer_count);
00676 
00677         JUNOS_KCOM_MPSDK_CFG_FREE(jkg);
00678 
00679         break;
00680 
00681     case MSVCS_CONTROL_EV_HA_INFO_BLOB:
00682 
00683         CLOG(LOG_INFO, "%s: HA Info Event", __func__);
00684 
00685         ha_info = (msvcs_ha_info_hdr_t *)mc_ctx->plugin_data;
00686 
00687         if(!ha_info) {
00688             CLOG(LOG_ERR, "%s: Malformed control event", __func__);
00689             break;
00690         }
00691 
00692         if(ha_info->subtype == MSVCS_HA_INFO_REDUNDANCY_INFO) {
00693             CLOG(LOG_INFO, "%s: Received redundancy information of length %d",
00694                     __func__, ha_info->length);
00695 
00696             ri= (kcom_ifdev_redundancy_info_t *)MSVCS_HA_INFO_HDR_DATA(ha_info);
00697 
00698             switch(ri->state) {
00699             case KCOM_IFDEV_REDUNDANCY_STATE_WAITING_FOR_PRIMARY:
00700                 state = waiting_state;
00701                 break;
00702             case KCOM_IFDEV_REDUNDANCY_STATE_PRIMARY_ACTIVE:
00703                 state = primary_state;
00704                 break;
00705             case KCOM_IFDEV_REDUNDANCY_STATE_SECONDARY_ACTIVE:
00706                 state = secondary_state;
00707                 break;
00708             case KCOM_IFDEV_REDUNDANCY_STATE_NONE_ACTIVE:
00709                 state = none_state;
00710                 break;
00711             default:
00712                 state = tmp1;
00713                 snprintf(tmp1, sizeof(tmp1), "%d", (int)ri->state);
00714                 break;
00715             }
00716 
00717             switch(ri->cmd) {
00718             case KCOM_IFDEV_REDUNDANCY_CMD_NONE:
00719                 op = no_op;
00720                 break;
00721             case KCOM_IFDEV_REDUNDANCY_CMD_SWITCH:
00722                 op = switch_op;
00723                 break;
00724             case KCOM_IFDEV_REDUNDANCY_CMD_REVERT:
00725                 op = revert_op;
00726                 break;
00727             default:
00728                 op = tmp2;
00729                 snprintf(tmp2, sizeof(tmp2), "%d", (int)ri->cmd);
00730                 break;
00731             }
00732 
00733             CLOG(LOG_INFO, "State: %s, Cmd: %s, "
00734                     "Time since last change Sec: %ld, uSec: %ld, "
00735                     "Primary: %s, Secondary: %s, Active: %s", state, op,
00736                     ri->lastupdate.tv_sec, ri->lastupdate.tv_usec,
00737                     ri->primary_ifdev_name, ri->secondary_ifdev_name,
00738                     ri->active_ifdev_name);
00739 
00740         } else {
00741             CLOG(LOG_ERR, "%s: Received unrecognizable HA info", __func__);
00742         }
00743 
00744         free(ha_info);
00745 
00746         break;
00747 
00748     default:
00749         CLOG(LOG_ERR, "%s: Received an unhandled ctrl event %X", __func__, ev);
00750     }
00751 
00752     return MSP_OK;
00753 }
00754 
00755 
00756 /*** GLOBAL/EXTERNAL Functions ***/
00757 
00758 int passthru_entry(void);
00759 
00767 int
00768 passthru_entry(void)
00769 {
00770     msvcs_plugin_params_t params;
00771 
00772     CLOG(LOG_INFO, "%s: Registering plug-in in entry function from CPU %d.",
00773             __func__, msvcs_state_get_cpuid());
00774     
00775     // Register plug-in itself
00776 
00777     bzero(&params, sizeof(msvcs_plugin_params_t));
00778 
00779     strlcpy(params.spp_name, PASSTHRU_PLUGIN_NAME, sizeof(params.spp_name));
00780     params.spp_plugin_app_id = PASSTHRU_PLUGIN_ID;
00781     params.spp_class = MSVCS_PLUGIN_CLASS_EXTERNAL;
00782     params.spp_data_evh = passthru_data_hdlr;
00783     params.spp_control_evh = passthru_ctrl_hdlr;
00784 
00785 #if CONFIG_MODE == NO_POLICY_DATABASE
00786     // Enable this to make the plugin a packet-based processing plugin
00787     // where no session is created only for this service set
00788 
00789     params.spp_plugin_flags |= MSVCS_PLUGIN_FLAGS_IGNORE_POLICY;
00790 #endif
00791 
00792     plugin_id = msvcs_plugin_register(&params);
00793 
00794     if (plugin_id < 0) {
00795         CLOG(LOG_ALERT, "%s: %s cannot be registered as a valid plug-in",
00796                 __func__, PASSTHRU_PLUGIN_NAME);
00797     } else {
00798         CLOG(LOG_INFO, "%s: %s was successfully registered and assigned id"
00799                 "%d.", __func__, PASSTHRU_PLUGIN_NAME, plugin_id);
00800     }
00801 
00802     return plugin_id;
00803 }
00804 

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 Passthru Plug-in Example: passthru-plugin 1.0 by Doxygen 1.5.1