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