Bart,

Thank you for the advice.  It helped me learn more about the Net-SNMP
library, but unfortunately it did not solve the issue with
uninitialized syscall data.

I used memset() to initialize the "struct snmp_session" before passing
it to snmp_sess_init(), but I cannot memset() the "struct snmp_pdu"
because it is allocated and initialized by snmp_pdu_create() before I
can do any initialization.

I also tried adding null byte padding to the end of the character
arrays pointed to in the "hosts" and "oids" arrays in the async app (
http://www.net-snmp.org/wiki/index.php/TUT:Simple_Async_Application ).
 The initialization did not stop the valgrind errors (see attached
files asyncapp.c and gdb.log).

I think in the function header in snmpUDPDomain.c:184:

static int netsnmp_udp_send(netsnmp_transport *t, void *buf, int size,
void **opaque, int *olength)

"void *buf" is actually a "struct snmp_session *"/"netsnmp_session *",
but I do not know what type "void **opaque" is.  I noticed that the
"peername" pointer in "buf" is invalid when examining with gdb (see
attached file gdb.log) :

peername = 0x114c10000 <Address 0x114c10000 out of bounds>

Here's the valgrind error message again from the asynchronous context
in case you have any other thoughts:

==798== 8 errors in context 2 of 7:
==798== Syscall param ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ
points to uninitialised byte(s)
==798==    at 0x51C2A60: __sendmsg_nocancel (in /lib64/libc-2.10.1.so)
==798==    by 0x4E8BB0F: netsnmp_udp_send (snmpUDPDomain.c:184)
==798==    by 0x4E60AB2: snmp_sess_async_send (snmp_api.c:4862)
==798==    by 0x401315: asynch_response (asyncapp.c:188)
==798==    by 0x4E64BB0: _sess_process_packet (snmp_api.c:5239)
==798==    by 0x4E669B3: _sess_read (snmp_api.c:5742)
==798==    by 0x4E671B0: snmp_sess_read (snmp_api.c:5761)
==798==    by 0x4E671F1: snmp_read (snmp_api.c:5378)
==798==    by 0x401045: asynchronous (asyncapp.c:254)
==798==    by 0x4014E4: main (asyncapp.c:276)
==798==  Address 0x7fefff6c8 is on thread 1's stack
==798==  Uninitialised value was created by a stack allocation
==798==    at 0x4E8B9A2: netsnmp_udp_send (snmpUDPDomain.c:246)

Thank you,

Brendan


On Sat, May 29, 2010 at 02:18, Bart Van Assche <[email protected]> wrote:
> 2010/5/28 Brendan Tauras <[email protected]>
>>
>> I am writing an asynchronous polling application and testing it for
>> memory leaks with valgrind.  I got valgrind errors regarding system
>> call parameters pointing to uninitiailzed data on the stack (but the
>> program runs as expected).
>>
>> Then I ran the simple asynchronous application tutorial code (
>> http://www.net-snmp.org/wiki/index.php/TUT:Simple_Async_Application )
>> with valgrind and found the same issues (but the program runs as
>> expected).  I modified all hosts[i].name to "localhost" in the code so
>> I could query my local host's configured snmpd.
>>
>> I attached the valgrind output with meaningful backtraces (see the
>> error summary section).  Could you please explain this issue and what
>> I should do to correct it?
>>
>> I would also like to enable more debugging; what debugging symbols
>> would you recommend?  How would you recommend defining _DBG_IF_ and
>> ensuring NETSNMP_NO_DEBUGGING is undefined?
>
> Have you already tried to memset() the data structures passed to sendmsg()
> before these get initialized ? Such reports are typically caused by
> uninitialized padding bytes.
>
> Bart.
>
/*
 * NET-SNMP demo
 *
 * This program demonstrates different ways to query a list of hosts
 * for a list of variables.
 *
 * It would of course be faster just to send one query for all variables,
 * but the intention is to demonstrate the difference between synchronous
 * and asynchronous operation.
 *
 * Niels Baggesen ([email protected]), 1999.
 */

#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>

#ifdef HAVE_WINSOCK_H
#include <winsock.h>
#endif

/* DEBUG
 * Added null characters in attempt to force initialization of padding bytes.
 * String length should be (4k - 1) for 32-bit systems because literal strings
 * add 1 null character to the end of the string. */
/*
 * a list of hosts to query
 */
struct host {
        const char *name;
        const char *community;
} hosts[] = {
        { "localhost\0\0",              "v2com\0\0" },
        { "localhost\0\0",              "v2com\0\0" },
        { "localhost\0\0",              "v2com\0\0" },
        { "localhost\0\0",              "v2com\0\0" },
        { NULL }
};

/* DEBUG: use OID names that are parsable by read_objid() on my system */
/*
 * a list of variables to query for
 */
struct oid {
        const char *Name;
        oid Oid[MAX_OID_LEN];
        int OidLen;
} oids[] = {
        { "SNMPv2-MIB::sysDescr.0\0" },
        { "IF-MIB::ifNumber.1\0" },
        { "IF-MIB::ifNumber.0\0" },
        { NULL }
};
        /* { "system.sysDescr.0\0\0" }, */
        /* { "interfaces.ifNumber.1\0\0" }, */
        /* { "interfaces.ifNumber.0\0\0" }, */

        /* { "SNMPv2-MIB::sysDescr.0\0" }, */
        /* { "IF-MIB::ifNumber.1\0" }, */
        /* { "IF-MIB::ifNumber.0\0" }, */

        /* { ".1.3.6.1.2.1.1.1.0\0\0" }, */
        /* { ".1.3.6.1.2.1.2.1.1\0\0" }, */
        /* { ".1.3.6.1.2.1.2.1.0\0\0" }, */


/*
 * initialize
 */
void initialize (void)
{
        struct oid *op = oids;
        
        /* Win32: init winsock */
        SOCK_STARTUP;

        /* DEBUG: init data */
        int i;
        for(i = 0; i < 3; i++){
                memset(&(oids[i].Oid), 0, MAX_OID_LEN);
                oids[i].OidLen = 0;
        }

        /* initialize library */
        init_snmp("asynchapp");

        /* parse the oids */
        while (op->Name) {
                op->OidLen = sizeof(op->Oid)/sizeof(op->Oid[0]);
                if (!read_objid(op->Name, op->Oid, &op->OidLen)) {
                        snmp_perror("read_objid");
                        exit(1);
                }
                op++;
        }
}

/*
 * simple printing of returned data
 */
int print_result (int status, struct snmp_session *sp, struct snmp_pdu *pdu)
{
        char buf[1024];
        struct variable_list *vp;
        int ix;
        struct timeval now;
        struct timezone tz;
        struct tm *tm;

        gettimeofday(&now, &tz);
        tm = localtime(&now.tv_sec);
        fprintf(stdout, "%.2d:%.2d:%.2d.%.6d ", tm->tm_hour, tm->tm_min, 
tm->tm_sec,
                                        now.tv_usec);
        switch (status) {
        case STAT_SUCCESS:
                vp = pdu->variables;
                if (pdu->errstat == SNMP_ERR_NOERROR) {
                        while (vp) {
                                snprint_variable(buf, sizeof(buf), vp->name, 
vp->name_length, vp);
                                fprintf(stdout, "%s: %s\n", sp->peername, buf);
        vp = vp->next_variable;
                        }
                }
                else {
                        for (ix = 1; vp && ix != pdu->errindex; vp = 
vp->next_variable, ix++)
                                ;
                        if (vp) snprint_objid(buf, sizeof(buf), vp->name, 
vp->name_length);
                        else strcpy(buf, "(none)");
                        fprintf(stdout, "%s: %s: %s\n",
                                sp->peername, buf, 
snmp_errstring(pdu->errstat));
                }
                return 1;
        case STAT_TIMEOUT:
                fprintf(stdout, "%s: Timeout\n", sp->peername);
                return 0;
        case STAT_ERROR:
                snmp_perror(sp->peername);
                return 0;
        }
        return 0;
}

/*****************************************************************************/

/*
 * simple synchronous loop
 */
void synchronous (void)
{
        struct host *hp;

        for (hp = hosts; hp->name; hp++) {
                struct snmp_session ss, *sp;
                struct oid *op;

                /* DEBUG: zero-out the session struct */
                memset((void *) &ss, 0, sizeof(struct snmp_session));

                snmp_sess_init(&ss);                    /* initialize session */
                ss.version = SNMP_VERSION_2c;
                ss.peername = strdup(hp->name);
                ss.community = strdup(hp->community);
                ss.community_len = strlen(ss.community);
                if (!(sp = snmp_open(&ss))) {
                        snmp_perror("snmp_open");
                        continue;
                }
                for (op = oids; op->Name; op++) {
                        struct snmp_pdu *req, *resp;
                        int status;
                        req = snmp_pdu_create(SNMP_MSG_GET);
                        snmp_add_null_var(req, op->Oid, op->OidLen);
                        status = snmp_synch_response(sp, req, &resp);
                        if (!print_result(status, sp, resp)) break;
                        snmp_free_pdu(resp);
                }
                snmp_close(sp);
        }
}

/*****************************************************************************/

/*
 * poll all hosts in parallel
 */
struct session {
        struct snmp_session *sess;              /* SNMP session data */
        struct oid *current_oid;                /* How far in our poll are we */
} sessions[sizeof(hosts)/sizeof(hosts[0])];

int active_hosts;                       /* hosts that we have not completed */

/*
 * response handler
 */
int asynch_response(int operation, struct snmp_session *sp, int reqid,
                                struct snmp_pdu *pdu, void *magic)
{
        struct session *host = (struct session *)magic;
        struct snmp_pdu *req;

        if (operation == NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) {
                if (print_result(STAT_SUCCESS, host->sess, pdu)) {
                        host->current_oid++;                    /* send next 
GET (if any) */
                        if (host->current_oid->Name) {
                                req = snmp_pdu_create(SNMP_MSG_GET);
                                snmp_add_null_var(req, host->current_oid->Oid, 
host->current_oid->OidLen);
                                if (snmp_send(host->sess, req))
                                        return 1;
                                else {
                                        snmp_perror("snmp_send");
                                        snmp_free_pdu(req);
                                }
                        }
                }
        }
        else
                print_result(STAT_TIMEOUT, host->sess, pdu);

        /* something went wrong (or end of variables) 
         * this host not active any more
         */
        active_hosts--;
        return 1;
}

void asynchronous(void)
{
        struct session *hs;
        struct host *hp;

        /* startup all hosts */

        for (hs = sessions, hp = hosts; hp->name; hs++, hp++) {
                struct snmp_pdu *req;
                struct snmp_session sess;

                /* DEBUG: zero-out the session struct */
                memset((void *) &sess, 0, sizeof(struct snmp_session));

                snmp_sess_init(&sess);                  /* initialize session */
                sess.version = SNMP_VERSION_2c;
                sess.peername = strdup(hp->name);
                sess.community = strdup(hp->community);
                sess.community_len = strlen(sess.community);
                sess.callback = asynch_response;                /* default 
callback */
                sess.callback_magic = hs;
                if (!(hs->sess = snmp_open(&sess))) {
                        snmp_perror("snmp_open");
                        continue;
                }
                hs->current_oid = oids;
                req = snmp_pdu_create(SNMP_MSG_GET);    /* send the first GET */
                snmp_add_null_var(req, hs->current_oid->Oid, 
hs->current_oid->OidLen);
                if (snmp_send(hs->sess, req))
                        active_hosts++;
                else {
                        snmp_perror("snmp_send");
                        snmp_free_pdu(req);
                }
        }

        /* loop while any active hosts */

        while (active_hosts) {
                int fds = 0, block = 1;
                fd_set fdset;
                struct timeval timeout;

                FD_ZERO(&fdset);
                snmp_select_info(&fds, &fdset, &timeout, &block);
                fds = select(fds, &fdset, NULL, NULL, block ? NULL : &timeout);
                if (fds < 0) {
                                perror("select failed");
                                exit(1);
                }
                if (fds)
                                snmp_read(&fdset);
                else
                                snmp_timeout();
        }

        /* cleanup */

        for (hp = hosts, hs = sessions; hp->name; hs++, hp++) {
                if (hs->sess) snmp_close(hs->sess);
        }
}

/*****************************************************************************/

int main (int argc, char **argv)
{
        initialize();

        printf("---------- synchronous -----------\n");
        synchronous();

        printf("---------- asynchronous -----------\n");
        asynchronous();

        return 0;
}
Function "netsnmp_udp_send" not defined.
Make breakpoint pending on future shared library load? (y or [n]) 
Breakpoint 1 (netsnmp_udp_send) pending.
$1 = 0x401714 "SNMPv2-MIB::sysDescr.0"
0x401714:       0x53    0x4e    0x4d    0x50    0x76    0x32    0x2d    0x4d
0x40171c:       0x49    0x42    0x3a    0x3a    0x73    0x79    0x73    0x44
0x401724:       0x65    0x73    0x63    0x72    0x2e    0x30    0x00    0x00
0x401714:       83 'S'  78 'N'  77 'M'  80 'P'  118 'v' 50 '2'  45 '-'  77 'M'
0x40171c:       73 'I'  66 'B'  58 ':'  58 ':'  115 's' 121 'y' 115 's' 68 'D'
0x401724:       101 'e' 115 's' 99 'c'  114 'r' 46 '.'  48 '0'  0 '\000'        
0 '\000'
Starting program: 
/home/btauras/proj/snmp_poller/examples/snmp-async-sample/asyncapp 

Breakpoint 1, netsnmp_udp_send (t=0x672980, buf=0x695b16, size=42, 
    opaque=0x694e00, olength=0x694e08) at snmpUDPDomain.c:246
246     snmpUDPDomain.c: No such file or directory.
        in snmpUDPDomain.c
$2 = {domain = 0x7ffff7dab8a0, domain_length = 7, local = 0x0, 
  local_length = 0, remote = 0x6831d0 "\177", remote_length = 6, sock = 6, 
  flags = 0, data = 0x68c6a0, data_length = 20, msgMaxSize = 65507, 
  f_recv = 0x7ffff7b7cdaf <netsnmp_udp_recv>, 
  f_send = 0x7ffff7b7b9a2 <netsnmp_udp_send>, 
  f_close = 0x7ffff7b7b984 <netsnmp_udp_close>, f_accept = 0, 
  f_fmtaddr = 0x7ffff7b7b8a0 <netsnmp_udp_fmtaddr>}
$3 = {version = 8504207873717446704, retries = 1836016434, 
  timeout = 144116299101535799, flags = 578163002699677697, 
  subsession = 0x101010201062b, next = 0x5, 
  peername = 0x114c10000 <Address 0x114c10000 out of bounds>, remote_port = 0, 
  localname = 0x0, local_port = 0, authenticator = 0, callback = 0, 
  callback_magic = 0x0, s_errno = 0, s_snmp_errno = 0, sessid = 0, 
  community = 0x0, community_len = 0, rcvMsgMaxSize = 0, sndMsgMaxSize = 0, 
  isAuthoritative = 0 '\000', contextEngineID = 0x0, contextEngineIDLen = 0, 
  engineBoots = 0, engineTime = 0, contextName = 0x0, contextNameLen = 0, 
  securityEngineID = 0x0, securityEngineIDLen = 0, securityName = 0x0, 
  securityNameLen = 0, securityAuthProto = 0x0, securityAuthProtoLen = 0, 
  securityAuthKey = '\000' <repeats 31 times>, securityAuthKeyLen = 0, 
  securityAuthLocalKey = 0x0, securityAuthLocalKeyLen = 0, 
  securityPrivProto = 0x0, securityPrivProtoLen = 0, 
  securityPrivKey = '\000' <repeats 31 times>, securityPrivKeyLen = 0, 
  securityPrivLocalKey = 0x0, securityPrivLocalKeyLen = 0, securityModel = 0, 
  securityLevel = 0, paramName = 0x0, securityInfo = 0x0, myvoid = 0x0}
Continuing.

Breakpoint 1, netsnmp_udp_send (t=0x672980, buf=0x696516, size=42, 
    opaque=0x609520, olength=0x609528) at snmpUDPDomain.c:246
246     in snmpUDPDomain.c
$4 = {domain = 0x7ffff7dab8a0, domain_length = 7, local = 0x0, 
  local_length = 0, remote = 0x6831d0 "\177", remote_length = 6, sock = 6, 
  flags = 0, data = 0x68c6a0, data_length = 20, msgMaxSize = 65507, 
  f_recv = 0x7ffff7b7cdaf <netsnmp_udp_recv>, 
  f_send = 0x7ffff7b7b9a2 <netsnmp_udp_send>, 
  f_close = 0x7ffff7b7b984 <netsnmp_udp_close>, f_accept = 0, 
  f_fmtaddr = 0x7ffff7b7b8a0 <netsnmp_udp_fmtaddr>}
$5 = {version = 8504207873717446704, retries = 1836016434, 
  timeout = 144116299118313015, flags = 578163002699677697, 
  subsession = 0x10102010201062b, next = 0x5, 
  peername = 0x10ac10000 <Address 0x10ac10000 out of bounds>, remote_port = 0, 
  localname = 0x0, local_port = 0, authenticator = 0, callback = 0, 
  callback_magic = 0x0, s_errno = 0, s_snmp_errno = 0, sessid = 0, 
  community = 0x0, community_len = 0, rcvMsgMaxSize = 0, sndMsgMaxSize = 0, 
  isAuthoritative = 0 '\000', contextEngineID = 0x0, contextEngineIDLen = 0, 
  engineBoots = 0, engineTime = 0, contextName = 0x0, contextNameLen = 0, 
  securityEngineID = 0x0, securityEngineIDLen = 0, securityName = 0x0, 
  securityNameLen = 0, securityAuthProto = 0x0, securityAuthProtoLen = 0, 
  securityAuthKey = '\000' <repeats 31 times>, securityAuthKeyLen = 0, 
  securityAuthLocalKey = 0x0, securityAuthLocalKeyLen = 0, 
  securityPrivProto = 0x0, securityPrivProtoLen = 0, 
  securityPrivKey = '\000' <repeats 31 times>, securityPrivKeyLen = 0, 
  securityPrivLocalKey = 0x0, securityPrivLocalKeyLen = 0, securityModel = 0, 
  securityLevel = 0, paramName = 0x0, securityInfo = 0x0, myvoid = 0x0}
Continuing.

Program exited normally.
quit
------------------------------------------------------------------------------
ThinkGeek and WIRED's GeekDad team up for the Ultimate 
GeekDad Father's Day Giveaway. ONE MASSIVE PRIZE to the 
lucky parental unit.  See the prize list and enter to win: 
http://p.sf.net/sfu/thinkgeek-promo
_______________________________________________
Net-snmp-coders mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/net-snmp-coders

Reply via email to