[insert project logo here (125x200px max)]

Navigator

Mailinglists

Please report any errors or ommissions you find to our `Help' mailinglist, or post a message in the Forums.

Copyright and Licensing Information

Snap is (c) Jonathan T. Moore, 1999-2002 and licensed under the GNU General Public License (GPL).

All other parts of Splash are (c) Willem de Bruijn, 2002-2003 and licensed under the BSD Open Source License.

All sourcecode is made publicly available.

Acknowledgement

Splash and the Splash website are hosted by SourceForge.net

SourceForge.net Logo

osi-open source certified logo

Splash - Documentation

SNMP Plus a Lightweight API for SNAP Handling

Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

snap_svc/snap_svc_snmp.c

Go to the documentation of this file.
00001 /* snap service library                 */
00002 /* (c) Willem de Bruijn, 2002, 2003     */
00003 /* Licensed under the BSD License       */
00004 /* snap_svc_snmp library sourcefile     */
00005 
00006 #include <stdio.h>
00007 #include <string.h>
00008 
00009 #include <net-snmp/net-snmp-config.h>
00010 #include <net-snmp/net-snmp-includes.h>
00011 #include <net-snmp/definitions.h>
00012 #include <net-snmp/pdu_api.h>
00013 #include <net-snmp/agent/snmp_agent.h>
00014 
00015 #include "snap_svc.h"
00016 #include "snap_svc_snmp.h"
00017 #include "d_printf.h"
00018 
00019 /* referenced external variables */
00020 extern int      callback_master_num;                    /* some variable to reference the master */
00021 
00022 /* global variables*/
00023 unsigned short svc_snmp_active = 0;
00024 unsigned short svc_snmp_pdu_load = 0;   /* how many variables are we referencing? */
00025 netsnmp_pdu* svc_snmp_pdu = NULL;                       /* the pdu (really ;-) )*/
00026 netsnmp_session* svc_snmp_session = NULL;       /* the connection */
00027 int svc_snmp_pdu_waiting = 0;
00028 
00029 /* library handling functions */
00030 void snap_external_svclib_init(){
00031     if (snap_external_svclib_snmp_init(NULL))
00032         d_printf(50,"snap_svc_snmp : initialized\n");
00033 }
00034 
00035 void snap_external_svclib_done(){
00036 
00037     /* snmp lib specific */
00038     if (svc_snmp_pdu){
00039         snmp_free_pdu(svc_snmp_pdu);
00040         svc_snmp_pdu = NULL;
00041     }
00042     if (svc_snmp_session || svc_snmp_active)
00043         snap_external_svclib_snmp_close(NULL);
00044 
00045     svc_snmp_pdu_load = 0;
00046     svc_snmp_session = NULL;
00047     svc_snmp_pdu_waiting = 0;
00048 
00049     d_printf(50,"snap_svc_snmp : closed\n");
00050 }
00051 
00052 /* there is where functions inside the library should be listed for registration */
00053 void snap_external_svclib_getnextfunc(char** snapsvc_name, snapsvc_func_proto* snapsvc_func, int* snapsvc_args, int* snapsvc_rets){
00054 
00055     switch (svc_fun_counter){
00056         case 0  :   (*snapsvc_name) = strdup ("snmp_init");
00057                     (*snapsvc_func) = (snapsvc_func_proto) &snap_external_svclib_snmp_init;
00058                     (*snapsvc_args) = 0;
00059                     (*snapsvc_rets) = SVC_SNMP_TYPE_NULL;
00060                     break;
00061         case 1  :   (*snapsvc_name) = strdup ("snmp_init_ip");
00062                     (*snapsvc_func) = (snapsvc_func_proto) &snap_external_svclib_snmp_init_ip;
00063                     (*snapsvc_args) = 1;
00064                     (*snapsvc_rets) = SVC_SNMP_TYPE_NULL;
00065                     break;
00066         case 2  :   (*snapsvc_name) = strdup ("snmp_pdu_init");
00067                     (*snapsvc_func) = (snapsvc_func_proto) &snap_external_svclib_snmp_initpdu;
00068                     (*snapsvc_args) = 1;
00069                     (*snapsvc_rets) = SVC_SNMP_TYPE_NULL;
00070                     break;
00071         case 3  :   (*snapsvc_name) = strdup ("snmp_pdu_addvar_null");
00072                     (*snapsvc_func) = (snapsvc_func_proto) &snap_external_svclib_snmp_addvar_null;
00073                     (*snapsvc_args) = 1;
00074                     (*snapsvc_rets) = SVC_SNMP_TYPE_NULL;
00075                     break;
00076         case 4  :   (*snapsvc_name) = strdup ("snmp_pdu_addvar_withvalue");
00077                     (*snapsvc_func) = (snapsvc_func_proto) &snap_external_svclib_snmp_addvar_withvalue;
00078                     (*snapsvc_args) = 4;
00079                     (*snapsvc_rets) = SVC_SNMP_TYPE_NULL;
00080                     break;
00081         case 5  :   (*snapsvc_name) = strdup ("snmp_pdu_send");
00082                     (*snapsvc_func) = (snapsvc_func_proto) &snap_external_svclib_snmp_execpdu;
00083                     (*snapsvc_args) = 0;
00084                     (*snapsvc_rets) = SVC_SNMP_TYPE_NULL;
00085                     break;
00086         case 6  :   (*snapsvc_name) = strdup ("snmp_close");
00087                     (*snapsvc_func) = (snapsvc_func_proto) &snap_external_svclib_snmp_close;
00088                     (*snapsvc_args) = 0;
00089                     (*snapsvc_rets) = SVC_SNMP_TYPE_NULL;
00090                     break;
00091         case 7  :   (*snapsvc_name) = strdup ("snmp_getsingle");
00092                     (*snapsvc_func) = (snapsvc_func_proto) &snap_external_svclib_snmp_getsingle;
00093                     (*snapsvc_args) = 1;
00094                     (*snapsvc_rets) = SVC_SNMP_TYPE_NULL;
00095                     break;
00096         case 8  :   (*snapsvc_name) = strdup ("snmp_setsingle");
00097                     (*snapsvc_func) = (snapsvc_func_proto) &snap_external_svclib_snmp_setsingle;
00098                     (*snapsvc_args) = 4;
00099                     (*snapsvc_rets) = SVC_SNMP_TYPE_NULL;
00100                     break;
00101         case 9  :   (*snapsvc_name) = strdup ("snmp_getnexthop");
00102                     (*snapsvc_func) = (snapsvc_func_proto) &snap_external_svclib_snmp_getnexthopfromip;
00103                     (*snapsvc_args) = 1;
00104                     (*snapsvc_rets) = SVC_SNMP_TYPE_NULL;
00105                     break;
00106         case 10 :   (*snapsvc_name) = strdup ("snmp_getneighbours");
00107                     (*snapsvc_func) = (snapsvc_func_proto) &snap_external_svclib_snmp_getallotherneighboursfromip;
00108                     (*snapsvc_args) = 1;
00109                     (*snapsvc_rets) = SVC_SNMP_TYPE_NULL;
00110                     break;
00111         /* unknown handler -> return NULL as end-of-list symbol */
00112         default :   (*snapsvc_name) = NULL;
00113                     (*snapsvc_func) = NULL;
00114                     (*snapsvc_args) = 0;
00115                     (*snapsvc_rets) = 0;
00116     }
00117     svc_fun_counter ++;
00118 }
00119 
00120 /* snmp callback handler*/
00121 int snap_external_svclib_snmp_INTERNAL_execpdu_handler(int op, netsnmp_session * session, int reqid,
00122                          netsnmp_pdu *pdu, void *useless){
00123     netsnmp_variable_list* curlist;
00124     int count = 0;
00125 
00126     if (op == NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE ){
00127 
00128         /* create a structure to hold the results */
00129         curlist = pdu->variables;
00130         while (curlist){
00131             count++;
00132             curlist = curlist->next_variable;
00133         }
00134         snap_external_svclib_free_local_returnstruct();
00135         svc_return = (struct svc_returnstruct*) calloc (1,sizeof(struct svc_returnstruct));
00136         svc_return->length = count;
00137         svc_return->list = (struct svc_returnitem*) calloc (count,sizeof(struct svc_returnitem));
00138 
00139         /* write data to SNAP stack */
00140         curlist = pdu->variables;
00141         count = 0;
00142         while(curlist){
00143             /* simply walk the available options and select the necessary one */
00144             /*
00145                 NB: net-snmp uses a #ifdef OPAQUE_SPECIAL_TYPES top add the float
00146                 and double type. We will adhere to the failsafe case == undefined
00147             */
00148 
00149             /* copy the OID */
00150             svc_return->list[count].oid_length = curlist->name_length;
00151             svc_return->list[count].oid = calloc (curlist->name_length, sizeof(unsigned long));
00152             memmove(svc_return->list[count].oid, curlist->name, curlist->name_length * sizeof(unsigned long));
00153 
00154             /* copy the value length */
00155             svc_return->list[count].length = curlist->val_len;
00156 
00157             /* copy the value */
00158             switch(curlist->type){
00159                 case ASN_BIT_STR : case ASN_OCTET_STR :
00160                     svc_return->list[count].type = SVC_SNMP_TYPE_STRING;
00161                     svc_return->list[count].data = calloc (curlist->val_len, sizeof(u_char));
00162                     memmove(svc_return->list[count].data,curlist->val.string,curlist->val_len);
00163                     break;
00164                 case ASN_IPADDRESS :
00165                     svc_return->list[count].type = SVC_SNMP_TYPE_ADDR;
00166                     svc_return->list[count].data = calloc (curlist->val_len, sizeof(uint32_t));
00167                     memmove(svc_return->list[count].data,curlist->val.integer,sizeof(uint32_t));
00168                     break;
00169                 case ASN_BOOLEAN : case ASN_INTEGER :
00170                 case ASN_TIMETICKS :
00171                 case ASN_COUNTER : case ASN_GAUGE : /* case ASN_UNSIGNED : is the same as ASN_GAUGE */
00172                     svc_return->list[count].type = SVC_SNMP_TYPE_INT;
00173                     svc_return->list[count].data = calloc (curlist->val_len, sizeof(int));
00174                     memmove(svc_return->list[count].data,curlist->val.integer,curlist->val_len);
00175                     break;
00176                 case ASN_OBJECT_ID :
00177                     svc_return->list[count].type = SVC_SNMP_TYPE_LONG;
00178                     svc_return->list[count].data = calloc (curlist->val_len, sizeof(unsigned long));
00179                     memmove(svc_return->list[count].data,curlist->val.string,curlist->val_len);
00180                     break;
00181                 case ASN_COUNTER64 :
00182                     svc_return->list[count].type = SVC_SNMP_TYPE_LONG;
00183                     svc_return->list[count].data = calloc (curlist->val_len, sizeof(unsigned long));
00184                     ((unsigned long*) svc_return->list[count].data)[0] = curlist->val.counter64->high;
00185                     ((unsigned long*) svc_return->list[count].data)[1] = curlist->val.counter64->low;
00186                     svc_return->list[count].length = 2; /* override general case */
00187                     break;
00188                 case ASN_NULL :
00189                     svc_return->list[count].type = SVC_SNMP_TYPE_NULL;
00190                     svc_return->list[count].data = NULL;
00191                     svc_return->list[count].length = 0;
00192                     break;
00193                 default :
00194                     svc_return->list[count].type = SVC_SNMP_TYPE_NULL;
00195                     svc_return->list[count].data = NULL;
00196                     svc_return->list[count].length = 0;
00197                     d_printf(10,"snap_svc_snmp : received value of unknown ASN type [%d], treating it as NULL\n",curlist->type);
00198             }
00199             curlist = curlist->next_variable;
00200             count ++;
00201 
00202         }
00203 
00204         /* notify our waiting function */
00205         svc_snmp_pdu_waiting = 0;
00206         return 1;
00207     }
00208     else{
00209         d_printf(10,"snap_svc_snmp : received error message %d while expecting result\n",op);
00210         if (op == 2){ /* timeout */
00211             svc_snmp_pdu_waiting = 0;
00212         }
00213         return 0;
00214     }
00215 }
00216 
00217 /* ADD SERVICES BELOW */
00218 /* declarations of snap service handlers */
00219 
00220 
00221 int snap_external_svclib_snmp_init(void* useless){
00222     if (svc_snmp_active)
00223          snap_external_svclib_snmp_close(NULL);
00224 
00225     SOCK_STARTUP;
00226 
00227 
00228     svc_snmp_session = netsnmp_callback_open(callback_master_num,
00229                                                      snap_external_svclib_snmp_INTERNAL_execpdu_handler,
00230                                                      NULL, NULL);
00231     if (svc_snmp_session == NULL) {
00232         d_printf(50,"snap_svc_snmp : error while opening callback transport \n");
00233         return 1;
00234     }
00235 
00236     svc_snmp_active = 1;
00237     return 0;
00238 }
00239 
00240 int snap_external_svclib_snmp_init_ip(unsigned int ip){
00241     if (svc_snmp_active)
00242          snap_external_svclib_snmp_close(NULL);
00243 
00244     
00245     SOCK_STARTUP;
00246 
00247 
00248     svc_snmp_session = calloc( sizeof(netsnmp_session), 1);
00249     snmp_sess_init( svc_snmp_session );                   /* set up defaults */
00250     svc_snmp_session->peername = malloc (sizeof(char) * 16);
00251     sprintf(svc_snmp_session->peername,"%u.%u.%u.%u",ip << 24 >> 24, ip << 16 >> 24, ip << 8 >> 24, ip >> 24);
00252     
00253     d_printf(110,"snap_svc_snmp_ip : trying ip %s\n",svc_snmp_session->peername);
00254     svc_snmp_session->callback = snap_external_svclib_snmp_INTERNAL_execpdu_handler;
00255     svc_snmp_session->remote_port = 161;
00256     svc_snmp_session->version = SNMP_VERSION_2c;
00257     svc_snmp_session->community = strdup("public");
00258     svc_snmp_session->community_len = 6;
00259         
00260     svc_snmp_session = snmp_open(svc_snmp_session);
00261     if ( svc_snmp_session == NULL) {
00262         d_printf(50,"snap_svc_snmp : error while opening ip transport \n");
00263         snmp_perror("snap_svc_snmp");
00264         return 1;
00265     }
00266     
00267     svc_snmp_active = 1;
00268     return 0;
00269 }
00270 
00271 int snap_external_svclib_snmp_initpdu(unsigned int msg_type){
00272     /* open a connection if it does not yet exist */
00273     if (!svc_snmp_session)
00274         snap_external_svclib_snmp_init(NULL);
00275 
00276     d_printf(200,"snap_svc_snmp : message type is %u\n",msg_type);
00277     /* remove the current pdu if it exists */
00278     if (svc_snmp_pdu){
00279         snmp_free_pdu(svc_snmp_pdu);
00280         svc_snmp_pdu = NULL;
00281         svc_snmp_pdu_load = 0;
00282     }
00283 
00284     /* initialize the pdu */
00285     svc_snmp_pdu = snmp_pdu_create(msg_type);
00286     if (svc_snmp_pdu == NULL){
00287         d_printf(10,"snap_svc_snmp : error creating a PDU \n");
00288         return 1;
00289     }
00290 
00291     svc_snmp_pdu->version = SNMP_VERSION_2c; /* keep the communication as simple as possible */
00292     svc_snmp_pdu->securityName = strdup("anonymousSecName001");
00293     svc_snmp_pdu->securityNameLen = 19;
00294     svc_snmp_pdu->securityModel = SNMP_SEC_MODEL_ANY;
00295     svc_snmp_pdu->errindex = 0;
00296     svc_snmp_pdu->community = strdup("public");
00297     svc_snmp_pdu->community_len = 6;
00298     svc_snmp_pdu->flags = svc_snmp_pdu->flags | UCD_MSG_FLAG_ALWAYS_IN_VIEW; /* BEWARE: this statement makes the system bypasse the access control code */
00299     svc_snmp_pdu_load = 0;
00300 
00301     return 0;
00302 }
00303 
00304 int snap_external_svclib_snmp_addvar_null(char* name){
00305     oid my_oid[MAX_OID_LEN];
00306     int my_oid_length = MAX_OID_LEN;
00307 
00308     if (!svc_snmp_pdu){
00309         int msgtype = SNMP_MSG_GET;
00310         snap_external_svclib_snmp_initpdu(msgtype);
00311     }
00312 
00313     /* convert the string encoded name to an oid and add the variable */
00314     d_printf(100,"snap_svc_snmp : finding OID for string %s\n",name);
00315     if (!snmp_parse_oid(name, my_oid,&my_oid_length)){
00316         d_printf(20,"snap_svc_snmp : unable to create OID from input string, received SNMP error code %d\n",snmp_errno);
00317         return 1;
00318     }
00319 
00320     if (snmp_add_null_var(svc_snmp_pdu, my_oid, my_oid_length) == NULL){
00321         d_printf(20,"snap_svc_snmp : unable to add variable to the PDU, received SNMP error code %d\n",snmp_errno);
00322         return 1;
00323     }
00324 
00325     return 0;
00326 }
00327 
00328 int snap_external_svclib_snmp_addvar_withvalue(char* name, int type, void* value, int valuelen){
00329     oid my_oid[MAX_OID_LEN];
00330     int my_oid_length = MAX_OID_LEN;
00331 
00332     if (!svc_snmp_pdu){
00333         int msgtype = SNMP_MSG_SET;
00334         snap_external_svclib_snmp_initpdu(msgtype);
00335     }
00336 
00337     /* convert the string encoded name to an oid and add the variable */
00338     if (!snmp_parse_oid(name, my_oid,&my_oid_length)){
00339         d_printf(20,"snap_svc_snmp : unable to create OID from input string, received SNMP error code %d\n",snmp_errno);
00340         return 1;
00341     }
00342 
00343     if (snmp_pdu_add_variable(svc_snmp_pdu, my_oid, my_oid_length, type, value, valuelen) == NULL){
00344         d_printf(20,"snap_svc_snmp : unable to add variable to the PDU\n");
00345         return 1;
00346     }
00347 
00348     return 0;
00349 }
00350 
00351 int snap_external_svclib_snmp_execpdu(void* useless){
00352 
00353     /* do some safety checks */
00354     if (!svc_snmp_pdu){
00355         d_printf(10, "snap_svc_snmp : no PDU initialized, unable to send it");
00356         return 1;
00357     }
00358 
00359     /* send the PDU */
00360     d_printf_timed(5,"snap_svc_snmp : sending a request to SNMP ...\n");
00361     if (! snmp_send(svc_snmp_session, svc_snmp_pdu)){
00362         d_printf(10,"snap_svc_snmp : unable to send the request to the snmplibrary, received SNMP error code %d\n",snmp_errno);
00363         snmp_perror("snap_svc_snmp");
00364         snmp_free_pdu(svc_snmp_pdu);
00365         svc_snmp_pdu = NULL;
00366         return 1;
00367     }
00368 
00369     /* wait for handler to return */
00370     svc_snmp_pdu_waiting = 1;
00371     while (svc_snmp_pdu_waiting) {
00372         int fds = 0, block = 1;
00373         fd_set fdset;
00374         struct timeval timeout;
00375         timeout.tv_sec = 3; /* timeout in 3 secs */
00376         timeout.tv_usec = 0;
00377 
00378         d_printf(200,"snap_svc_snmp : ... waiting for a response ...\n");
00379         FD_ZERO(&fdset);
00380         snmp_select_info(&fds, &fdset, &timeout, &block);
00381         fds = select(fds, &fdset, NULL, NULL, block ? NULL : &timeout);
00382         if (fds)
00383             snmp_read(&fdset);
00384         else
00385             snmp_timeout();
00386     }
00387     d_printf_timed(5,"snap_svc_snmp : ... finished\n");
00388 
00389     /*
00390         if the request succeeded the pdu will be freed in the snmplib
00391         DO NOT FREE!
00392     */
00393     svc_snmp_pdu = NULL;
00394 
00395     if (svc_snmp_pdu_load != 0)
00396         svc_snmp_pdu_load = 0;
00397 
00398     return 0;
00399 }
00400 
00401 int snap_external_svclib_snmp_close(void* useless){
00402 
00403     if (svc_snmp_active){
00404         if (svc_snmp_pdu){
00405             snmp_free_pdu(svc_snmp_pdu);
00406             svc_snmp_pdu = NULL;
00407         }
00408 
00409         if (!svc_snmp_session)
00410             return 0;
00411 
00412         /* close the connection */
00413         if (!snmp_close(svc_snmp_session))
00414             d_printf(50,"snap_svc_snmp : I was unable to gracefully shut down the snmp connection, destroying... \n");
00415         svc_snmp_session = NULL;
00416 
00417         SOCK_CLEANUP;
00418 
00419         svc_snmp_active = 0;
00420     }
00421 
00422     return 0;
00423 }
00424 
00425 /* declarations of DERIVED snap service handlers */
00426 
00427 /* return a single value */
00428 int snap_external_svclib_snmp_getsingle(char* name){
00429   int msgtype = SNMP_MSG_GET;
00430 
00431   snap_external_svclib_snmp_initpdu(msgtype);
00432   snap_external_svclib_snmp_addvar_null(name);
00433   snap_external_svclib_snmp_execpdu(NULL);
00434 
00435   return 0;
00436 }
00437 
00438 /* set a single value */
00439 int snap_external_svclib_snmp_setsingle(char* name, int type, void* value, int valuelen){
00440   int msgtype = SNMP_MSG_SET;
00441 
00442   snap_external_svclib_snmp_initpdu(msgtype);
00443   snap_external_svclib_snmp_addvar_withvalue(name, type, value, valuelen);
00444   snap_external_svclib_snmp_execpdu(NULL);
00445 
00446   return 0;
00447 }
00448 
00449 /*
00450     find the incoming interface N from the last hop command IP (the in_IP)
00451     and calculate the next hop using ~ interface (N+1) mod (#ifaces)
00452 
00453 */
00454 
00455 int snap_external_svclib_snmp_getiface(unsigned long in_ip){
00456     char oid[100];
00457     int iface = -1;
00458 
00459     sprintf(oid,"ipAdEntIfIndex.%lu.%lu.%lu.%lu",in_ip << 24 >> 24, in_ip << 16 >> 24, in_ip << 8 >> 24, in_ip >> 24);
00460     d_printf(50,"oid = %s\n",oid);
00461     snap_external_svclib_snmp_getsingle(oid);
00462 
00463     if (svc_return->length == 1){
00464         if (svc_return->list[0].type == SVC_SNMP_TYPE_INT && svc_return->list[0].length == 4)
00465             iface = *((int*) svc_return->list[0].data);
00466         else
00467             d_printf(20,"ERROR >> wrong returntype or incorrect length [%d:%lu]\n",svc_return->list[0].type,svc_return->list[0].length);
00468     }
00469     else
00470         d_printf(20,"ERROR >> retrieving an incorrect number of results [%d]\n",svc_return->length);
00471 
00472     d_printf(50,"DEBUG >> iface = %d\n",iface);
00473     return iface;
00474 }
00475 
00476 unsigned long snap_external_svclib_snmp_gethop(int iface){
00477     int loopcount, dotcount;
00478     int msgtype = SNMP_MSG_GETBULK;
00479     char* out_ip = NULL;
00480     char oid[100];
00481     int ip_temp[4];
00482     unsigned long ip_address = 0;
00483 
00484     snap_external_svclib_snmp_initpdu(msgtype);
00485     svc_snmp_pdu->non_repeaters=0;
00486     svc_snmp_pdu->max_repetitions=10;
00487     snap_external_svclib_snmp_addvar_null("ipRouteIfIndex");
00488     snap_external_svclib_snmp_execpdu(NULL);
00489     d_printf(50,"DEBUG >> received bulk response with %d variables\n",svc_return->length);
00490     loopcount = 0;
00491     while (loopcount < svc_return->length){
00492         if (svc_return->list[loopcount].type == SVC_SNMP_TYPE_INT && svc_return->list[loopcount].length == 4){
00493             if ( *((int*) svc_return->list[loopcount].data) == iface){ /* if we have a hop on the right interface */
00494                 snprint_objid(oid,100,svc_return->list[loopcount].oid,svc_return->list[loopcount].oid_length);
00495                 if (!strncmp(oid,"RFC1213-MIB::ipRouteIfIndex",27)){
00496                     /* only keep the last part: the IP address */
00497                     loopcount = strlen(oid) - 1;
00498                     dotcount = 0;
00499                     while (loopcount && dotcount < 4){
00500                         if (oid[loopcount] == '.'){
00501                             dotcount ++;
00502                             ip_address += strtoul(&oid[loopcount],NULL,10) << dotcount * 8;
00503                             d_printf(50,"DEBUG >> ip so far = %ld, new = %d\n",ip_address,atoi(&oid[loopcount]));
00504                         }
00505                         loopcount --;
00506                     }
00507                     loopcount += 2; /* forget the last dot and the last loopcount-- */
00508                     out_ip = strdup (&oid[loopcount]);
00509                     d_printf(50,"DEBUG >> found a correct hop [%s], iface is %d\n",out_ip, iface);
00510                     loopcount = svc_return->length + 1; /* exit this while loop */
00511                 }
00512                 d_printf(20,"ERROR >> oid : %s, iface = %d\n",oid, iface);
00513             }
00514         }
00515         else
00516             d_printf(20,"ERROR >> wrong returntype or incorrect length [%d:%lu]\n",svc_return->list[loopcount].type,svc_return->list[loopcount].length);
00517         loopcount++;
00518     }
00519     if (loopcount != svc_return->length + 2)
00520             d_printf(10,"ERROR >> unable to find correct hop\n");
00521 
00522     /* convert from char to IP */
00523     if (out_ip){
00524         sscanf(out_ip,"%d.%d.%d.%d",&ip_temp[0],&ip_temp[1],&ip_temp[2],&ip_temp[3]);
00525         /*ip_address = ((unsigned long) ip_temp[0] << 24) & ((unsigned long) ip_temp[1] << 16) & ((unsigned long) (ip_temp[2] << 8)) & ((unsigned long) ip_temp[3]);
00526         */
00527         for (loopcount = 3; loopcount >= 0; loopcount--){
00528             ip_address = ip_address << 8;
00529             ip_address += ip_temp[loopcount];
00530         }
00531 
00532         d_printf(50,"DEBUG >> ip = %lu.%lu.%lu.%lu (long) == %s (string)\n",ip_address << 24 >> 24, ip_address << 16 >> 24, ip_address << 8 >> 24, ip_address >> 24, out_ip);
00533         free (out_ip);
00534     }
00535 
00536     return ip_address;
00537 
00538 }
00539 
00540 int snap_external_svclib_snmp_getifnumber(void* useless){
00541     int ifnumber = -1;
00542 
00543     snap_external_svclib_snmp_getsingle("ifNumber.0");
00544     if (svc_return->length == 1){
00545         if (svc_return->list[0].type == SVC_SNMP_TYPE_INT && svc_return->list[0].length == 4)
00546             ifnumber =  *((int*) svc_return->list[0].data);
00547         else
00548             d_printf(20,"ERROR >> wrong returntype or incorrect length [%d:%lu]\n",svc_return->list[0].type,svc_return->list[0].length);
00549     }
00550     else
00551         d_printf(20,"ERROR >> retrieving an incorrect number of results [%d]\n",svc_return->length);
00552 
00553     d_printf(50,"DEBUG >> ifNumber.0 = %d\n",ifnumber);
00554     return ifnumber;
00555 }
00556 
00557 int snap_external_svclib_snmp_isupiface(int iface){
00558     char oid[10];
00559     int status = -1;
00560 
00561     sprintf(oid,"ifOperStatus.%d",iface);
00562     snap_external_svclib_snmp_getsingle(oid);
00563     if (svc_return->length == 1){
00564         if (svc_return->list[0].type == SVC_SNMP_TYPE_INT && svc_return->list[0].length == 4)
00565             status =  *((int*) svc_return->list[0].data);
00566         else
00567             d_printf(20,"ERROR >> wrong returntype or incorrect length [%d:%lu]\n",svc_return->list[0].type,svc_return->list[0].length);
00568     }
00569     else
00570         d_printf(20,"ERROR >> retrieving an incorrect number of results [%d]\n",svc_return->length);
00571 
00572 
00573     d_printf(50,"DEBUG >> iface %d has status %d (1=up, 2=down)\n",iface, status);
00574     return status;
00575 }
00576 
00577 int snap_external_svclib_snmp_getnextiface(int old_iface){
00578     int ifnumber, isup = 0, count=0, iface;
00579     ifnumber = snap_external_svclib_snmp_getifnumber(NULL);
00580 
00581     iface = old_iface;
00582     if (iface != -1 && ifnumber != -1){
00583         do{
00584             if (iface < ifnumber)
00585                 iface ++ ;
00586             else
00587                 iface = 2;
00588             isup = snap_external_svclib_snmp_isupiface(iface);
00589             count++;
00590         } while (isup != 1 && count < ifnumber);
00591     }
00592 
00593     if (isup != 1)
00594         return -1;
00595     else
00596         return iface;
00597 }
00598 
00599 int snap_external_svclib_snmp_getnextifacefromip(unsigned long in_ip){
00600     int iface;
00601 
00602     iface = snap_external_svclib_snmp_getiface(in_ip);
00603     return snap_external_svclib_snmp_getnextiface(iface);
00604 }
00605 
00606 unsigned long snap_internal_svclib_snmp_getnexthopfromip(unsigned long in_ip){
00607     int iface;
00608     unsigned long ip = 0;
00609 
00610     iface = snap_external_svclib_snmp_getnextifacefromip(in_ip);
00611     if (iface != -1)
00612         ip = snap_external_svclib_snmp_gethop(iface);
00613 
00614     return ip;
00615 }
00616 
00617 unsigned long snap_external_svclib_snmp_getnexthopfromip(unsigned long in_ip){
00618     unsigned long ip = snap_internal_svclib_snmp_getnexthopfromip(in_ip);
00619 
00620     snap_external_svclib_free_local_returnstruct();
00621     svc_return = (struct svc_returnstruct*) calloc (1,sizeof(struct svc_returnstruct));
00622     svc_return->length = 1;
00623     svc_return->list = (struct svc_returnitem*) calloc (1,sizeof(struct svc_returnitem));
00624     svc_return->list[0].data = calloc (1, sizeof(unsigned long));
00625     memmove(svc_return->list[0].data,&ip,sizeof(unsigned long));
00626     svc_return->list[0].type = SVC_SNMP_TYPE_ADDR;
00627 
00628     return ip;
00629 }
00630 
00631 int snap_external_svclib_snmp_getallotherneighboursfromip(unsigned long in_ip){
00632     unsigned long ip = in_ip;
00633     int listcount=0, ifnumber, whilecount=2;
00634     struct svc_returnstruct* svc_temp;
00635 
00636     ifnumber = snap_external_svclib_snmp_getifnumber(NULL);
00637     ifnumber--; /* disregard the local interface */
00638     snap_external_svclib_free_local_returnstruct();
00639     svc_temp = (struct svc_returnstruct*) calloc (1,sizeof(struct svc_returnstruct));
00640     svc_temp->length = ifnumber + 1;
00641     svc_temp->list = (struct svc_returnitem*) calloc (ifnumber+1,sizeof(struct svc_returnitem));
00642     while(whilecount <= ifnumber + 1){
00643         d_printf(50,"DEBUG >> finding a hop for iface %d\n",whilecount);
00644         if (snap_external_svclib_snmp_isupiface(whilecount) == 1){
00645             ip = snap_external_svclib_snmp_gethop(whilecount);
00646             svc_temp->list[listcount].data = calloc (1, sizeof(unsigned long));
00647             memmove(svc_temp->list[listcount].data,&ip,sizeof(unsigned long));
00648             svc_temp->list[listcount].type = SVC_SNMP_TYPE_ADDR;
00649             listcount++;
00650             d_printf(50,"DEBUG >> visited an iface\n");
00651         }
00652         else{
00653             svc_temp->list[listcount].type = SVC_SNMP_TYPE_NULL;
00654             svc_temp->list[listcount].data = NULL;
00655             svc_temp->list[listcount].length = 0;
00656             listcount++;
00657         }
00658         whilecount++;
00659     }
00660 
00661     /* the #of new entries */
00662     svc_temp->list[ifnumber].type = SVC_SNMP_TYPE_INT;
00663     svc_temp->list[ifnumber].data = calloc (1, sizeof(int));
00664     memmove(svc_temp->list[ifnumber].data,&listcount,sizeof(int));
00665     snap_external_svclib_free_local_returnstruct();
00666     svc_return = svc_temp;
00667 /*  if (count != ifnumber)
00668         d_printf(50,"WARNING : found %d hops, only going to use %d\n",count,ifnumber);
00669 */
00670     return listcount;
00671 }