/* snmpb.c - snmpi bulk load */
static char *rcsid
= "$Header: /f/osi/snmp/RCS/snmpb.c,v 7.15 91/02/22 09:44:08 mrose Interim $";
* $Header: /f/osi/snmp/RCS/snmpb.c,v 7.15 91/02/22 09:44:08 mrose Interim $
* Contributed by NYSERNet Inc. This work was partially supported by the
* U.S. Defense Advanced Research Projects Agency and the Rome Air Development
* Center of the U.S. Air Force Systems Command under contract number
* Revision 7.15 91/02/22 09:44:08 mrose
* Revision 7.14 90/09/17 11:18:42 mrose
* Revision 7.13 90/09/10 13:52:21 mrose
* Revision 7.11 90/09/03 12:57:30 mrose
* Revision 7.10 90/08/28 10:29:24 mrose
* Revision 7.9 90/08/23 12:34:29 mrose
* Revision 7.8 90/08/20 21:25:56 mrose
* Revision 7.7 90/08/20 14:00:14 mrose
* Revision 7.6 90/08/19 16:26:25 mrose
* Revision 7.5 90/08/18 15:24:08 mrose
* Revision 7.4 90/08/18 01:28:40 mrose
* Revision 7.3 90/08/18 00:44:39 mrose
* Revision 7.2 90/08/16 16:50:37 mrose
* Revision 7.1 90/08/14 14:28:43 mrose
* Revision 7.0 90/08/08 14:00:19 mrose
* *** empty log message ***
* Acquisition, use, and distribution of this module and related
* materials are subject to the restrictions of a license agreement.
* Consult the Preface in the User's Manual for the full terms of
#define MAXTIME (60 * 1000L) /* in milli-seconds */
#define MINTIME 1 /* .. */
#define SETTLETIME 30 /* # of iterations to gauge RTT */
#define MAXTRIES 3 /* for retries */
#define MAXSPACE 0x10000 /* in between threads */
#define MAXTHREADS 10 /* maximum #-simultaneous */
static int RTTperthread
= MAXTIME
;
/* BINDING INFORMATION (results) */
#define b_value b_un.un_value
#define b_cols b_un.un_cols
/* INVOCATION INFORMATION */
struct type_SNMP_Message
*i_msg
;
int i_info
; /* info > 0: response
info < 0: not yet ready */
int i_rid
; /* request-id of interest */
int i_mid
; /* exclusive ceiling on i_rid */
PE i_pe
; /* message to retry */
int i_retries
; /* number of times request retried */
u_long i_lastime
; /* time last request sent */
int i_curinvokes
; /* current # threads when last request sent */
struct thread
*t_forw
; /* doubly-linked list */
struct thread
*t_back
; /* .. */
OID t_lo
; /* inclusive lower-bound */
OID t_arg
; /* current pointer */
OID t_hi
; /* exclusive upper-bound */
struct binding
*t_binding
; /* for bulk2_aux() */
struct invocation t_invoke
; /* invocation in progress */
#define t_msg t_invoke.i_msg
#define t_info t_invoke.i_info
#define t_rid t_invoke.i_rid
#define t_mid t_invoke.i_mid
#define t_pe t_invoke.i_pe
#define t_retries t_invoke.i_retries
#define t_lastime t_invoke.i_lastime
#define t_curinvokes t_invoke.i_curinvokes
int t_gns
; /* how many gn's done */
static int once_only
= 0;
static struct thread tque
; /* active thread list */
static struct thread
*THead
= &tque
;
static int curthreads
= 0;
static int maxthreads
= 0;
static int tothreads
= 0;
static int nilthreads
= 0;
static int dedthreads
= 0;
static int threadlimit
= MAXTHREADS
;
/* REQUEST INFORMATION */
struct request
*r_forw
; /* doubly-linked list */
struct request
*r_back
; /* .. */
int r_nbound
; /* number of bounds active */
OID r_lo
; /* inclusive lower bound */
OID r_arg
; /* current pointer */
OID r_hi
; /* exclusive upper bound */
int b_gns
; /* stats: how many gn's done */
struct invocation r_invoke
; /* invocation in progress... */
#define r_msg r_invoke.i_msg
#define r_info r_invoke.i_info
#define r_rid r_invoke.i_rid
#define r_mid r_invoke.i_mid
#define r_pe r_invoke.i_pe
#define r_retries r_invoke.i_retries
#define r_lastime r_invoke.i_lastime
#define r_curinvokes r_invoke.i_curinvokes
static struct request rque
; /* active request list */
static struct request
*RHead
= &rque
;
static int currequests
= 0;
static int maxrequests
= 0;
static int totbounds
= 0;
static int maxbounds
= 0;
static int nilbounds
= 0;
static int dedrequests
= 0;
static int boundlimit
= MAXBOUNDS
;
/* MISCELLANEOUS INFORMATION */
OID
oid_median (), oid_copy ();
void adios (), advise ();
/* algorithm assumes that first variable in VarBind has ubiquitous agent
bulk1 (ps
, sd
, vb
, community
)
struct type_SNMP_VarBindList
*vb
;
register struct thread
*t
;
register struct binding
**bp
;
timemin
= timemax
= timeout
;
curthreads
= maxthreads
= tothreads
= nilthreads
= dedthreads
= 0;
threadlimit
= MAXTHREADS
;
totreqs
= totretr
= totrsps
= totdups
= 0;
(void) gettimeofday (&tvs
, (struct timezone
*) 0);
timenow
= tvs
.tv_sec
* 1000L + tvs
.tv_usec
/ 1000L;
a
= oid_copy (arg
= vb
-> VarBind
-> name
);
a
-> oid_elements
[a
-> oid_nelem
++] = 127;
if (new_thread (ps
, vb
, community
, arg
, a
) == NOTOK
)
b
-> oid_elements
[b
-> oid_nelem
++] = 192;
if (new_thread (ps
, vb
, community
, a
, b
) == NOTOK
)
a
-> oid_elements
[(--a
-> oid_nelem
) - 1]++;
if (new_thread (ps
, vb
, community
, b
, a
) == NOTOK
)
bp
= &bl
, bl
= NULL
, rows
= 0;
for (timelap
= 0; THead
-> t_forw
!= THead
; timelap
++) {
register struct binding
*bv
;
if ((backoff
= wait_for_action (sd
, ps
)) == NOTOK
)
for (t
= THead
-> t_forw
; t
!= THead
; t
= u
) {
register struct binding
**bz
;
register struct type_SNMP_VarBindList
*vp
,
if (oid_cmp (t
-> t_arg
, b
= t
-> t_msg
-> data
-> un
.get__response
-> variable__bindings
-> VarBind
(void) strcpy (buffer
, oid2ode (t
-> t_arg
));
"agent botched get-next (%s -> %s), thread dead",
if (oid_cmp (b
, t
-> t_hi
) >= 0) {
t
-> t_arg
= oid_copy (b
);
a
= vb
-> VarBind
-> name
, b
= t
-> t_arg
;
oids
.oid_nelem
= b
-> oid_nelem
- a
-> oid_nelem
;
oids
.oid_elements
= b
-> oid_elements
+ a
-> oid_nelem
;
if ((bv
= (struct binding
*) calloc (1, sizeof *bv
)) == NULL
)
adios (NULLCP
, "out of memory");
*bp
= bv
, bp
= &bv
-> b_next
;
bv
-> b_name
= oid_copy (&oids
);
for (vp
= t
-> t_msg
-> data
-> un
.get__response
-> variable__bindings
, vb2
= vb
;
vp
= vp
-> next
, vb2
= vb2
-> next
) {
a
= vb2
-> VarBind
-> name
, b
= vp
-> VarBind
-> name
;
if (a
-> oid_nelem
> b
-> oid_nelem
|| bcmp ((char *) a
-> oid_elements
,
(char *) b
-> oid_elements
,
* sizeof a
-> oid_elements
[0])) {
vp
-> VarBind
-> name
= b
= oid_copy (t
-> t_arg
);
bcopy ((char *) a
-> oid_elements
,
(char *) b
-> oid_elements
,
a
-> oid_nelem
* sizeof *a
-> oid_elements
);
pe_free (vp -> VarBind -> value);
if ((vp -> VarBind -> value = pe_alloc (PE_CLASS_UNIV,
adios (NULLCP, "out of memory");
if ((bv
= (struct binding
*) calloc (1, sizeof *bv
)) == NULL
)
adios (NULLCP
, "out of memory");
*bz
= bv
, bz
= &bv
-> b_next
;
bv
-> b_name
= oid_copy (b
);
bv
-> b_value
= vp
-> VarBind
-> value
;
if ((vp
-> VarBind
-> value
= pe_alloc (PE_CLASS_UNIV
,
adios (NULLCP
, "out of memory");
if (curthreads
< threadlimit
&& (a
= oid_median (t
-> t_arg
, t
-> t_hi
))) {
if (new_thread (ps
, vb
, community
, a
, t
-> t_hi
) == NOTOK
)
remque (t
); /* fairness in splits... */
insque (t
, THead
-> t_back
);
if (next_thread (t
, ps
, 1) == NOTOK
)
advise (NULLCP
, "aborting bulk retrieval...");
while ((t
= THead
-> t_forw
) != THead
)
(void) gettimeofday (&now
, (struct timezone
*) 0);
now
.tv_sec
-= tvs
.tv_sec
;
if ((now
.tv_usec
-= tvs
.tv_usec
) < 0)
now
.tv_sec
--, now
.tv_usec
+= 1000000;
"%d row%s retrieved in %d.%06d seconds during %d iterations",
rows
, rows
!= 1 ? "s" : "", now
.tv_sec
, now
.tv_usec
, timelap
);
"threads: at most %d active, total of %d created, and %d did nothing",
maxthreads
, tothreads
, nilthreads
);
advise (NULLCP
, "messages: %d request%s sent, along with %d retr%s",
totreqs
, totreqs
!= 1 ? "s" : "", totretr
,
totretr
!= 1 ? "ies" : "y");
advise (NULLCP
, " %d response%s rcvd, along with %d duplicate%s",
totrsps
, totrsps
!= 1 ? "s" : "", totdups
,
totdups
!= 1 ? "s" : "");
advise (NULLCP
, "timeouts: min=%d.%03d fin=%d.%03d max=%d.%03d seconds",
timemin
/ 1000, timemin
% 1000, timeout
/ 1000, timeout
% 1000,
timemax
/ 1000, timemax
% 1000);
print_bulk (bl
, vb
, dedthreads
);
static int wait_for_action (sd
, ps
)
struct type_SNMP_Message
*msg
;
register struct type_SNMP_PDU
*parm
;
register struct invocation
*i
;
register struct request
*r
,
register struct thread
*t
,
for (t
= THead
-> t_forw
; t
!= THead
; t
= t
-> t_forw
) {
if (t
-> t_info
) /* should always fail... */
for (s
= t
-> t_forw
; s
!= THead
; s
= s
-> t_forw
)
if (!s
-> t_info
&& s
-> t_lastime
< t
-> t_lastime
)
if (lastime
> t
-> t_lastime
)
lastime
= t
-> t_lastime
;
for (r
= RHead
-> r_forw
; r
!= RHead
; r
= r
-> r_forw
) {
if (r
-> r_info
) /* should always fail... */
for (u
= r
-> r_forw
; u
!= RHead
; u
= u
-> r_forw
)
if (!u
-> r_info
&& u
-> r_lastime
< r
-> r_lastime
)
if (lastime
> r
-> r_lastime
)
lastime
= r
-> r_lastime
;
if ((maxrtt
= timeout
- (timenow
- lastime
)) < 0)
if (debug
&& maxrtt
< timeout
)
fprintf (stderr
, "timeout reduced from %u to %u (delta %d)\n",
timeout
, (u_long
) maxrtt
, (int) (timeout
- maxrtt
));
tvs
.tv_sec
= maxrtt
/ 1000L, tvs
.tv_usec
= (maxrtt
% 1000) * 1000L;
switch (n
= select (nfds
, &rfds
, NULLFD
, NULLFD
, &tvs
)) {
advise ("failed", "select");
(void) gettimeofday (&tvs
, (struct timezone
*) 0);
timenow
= tvs
.tv_sec
* 1000L + tvs
.tv_usec
/ 1000L;
if ((pe
= ps2pe (ps
)) == NULLPE
) {
advise (NULLCP
, "ps2pe: %s", ps_error (ps
-> ps_errno
));
if (decode_SNMP_Message (pe
, 1, NULLIP
, NULLVP
, &msg
) == NOTOK
) {
advise (NULLCP
, "decode_SNMP_Message: %s", PY_pepy
);
fprintf (stdout
, "read PDU\n");
(void) print_SNMP_Message (pe
, 1, NULLIP
, NULLVP
, NULLCP
);
if (msg
-> data
-> offset
!= type_SNMP_PDUs_get__response
) {
advise (NULLCP
, "unexpected message type %d",
(parm
= msg
-> data
-> un
.get__response
) -> request__id
;
for (t
= THead
-> t_forw
; t
!= THead
; t
= s
) {
if (t
-> t_rid
!= request_id
)
advise (NULLCP
, "duplicated response for request-id %d",
free_SNMP_Message (t
-> t_msg
);
if (parm
-> error__status
!= int_SNMP_error__status_noError
) {
if (parm
-> error__status
!= int_SNMP_error__status_noSuchName
)
advise (NULLCP
, "%s for get-next of %s, thread dead",
snmp_error (parm
-> error__status
),
for (r
= RHead
-> r_forw
; r
!= RHead
; r
= u
) {
if (r
-> r_rid
!= request_id
)
advise (NULLCP
, "duplicated response for request-id %d",
switch (parm
-> error__status
) {
case int_SNMP_error__status_noError
:
free_SNMP_Message (r
-> r_msg
);
case int_SNMP_error__status_tooBig
:
advise (NULLCP
, "got %s on request of size %d",
snmp_error (parm
-> error__status
),
if (1 < r
-> r_nbound
&& r
-> r_nbound
<= boundlimit
)
boundlimit
= r
-> r_nbound
- 1;
case int_SNMP_error__status_noSuchName
:
if (parm
-> error__index
== 0) {
"got %s with invalid index (%d)",
snmp_error (parm
-> error__status
),
register struct bound
*b
,
register struct type_SNMP_VarBindList
*v
,
vp
= &r
-> r_msg
-> data
-> un
.get__request
for (j
= parm
-> error__index
;
snmp_error (parm
-> error__status
),
oid2ode ((*bp
) -> r_arg
));
b
= *bp
, bp
= &b
-> r_next
;
v
= *vp
, vp
= &v
-> next
;
free_SNMP_VarBindList (v
);
advise (NULLCP
, "%s for get-next of %s, et. al.",
snmp_error (parm
-> error__status
),
oid2ode (r
-> r_bounds
-> r_arg
));
if (i
-> i_retries
== 0) {
long val
= timenow
- i
-> i_lastime
;
if (timelap
< SETTLETIME
) {
int rtt
= maxrtt
/ i
-> i_curinvokes
;
if (RTTperthread
> rtt
) {
if ((threadlimit
= i
-> i_curinvokes
+ 1)
threadlimit
= MAXTHREADS
;
"time now %u, xmit-time %u, RTT %u\n",
timenow
- i
-> i_lastime
);
fprintf (stderr
, "request-id mismatch, not expecting %d\n",
if (select_dgram_socket (nfds
, &rfds
, NULLFD
, NULLFD
, OK
) > OK
)
if (curthreads
> maxthreads
)
if (currequests
> maxrequests
)
maxrequests
= currequests
;
if ((timeout
<<= 1) > MAXTIME
)
fprintf (stderr
, "adjusted timeout to %g seconds(0)\n",
if (maxrtt
> 0 && maxrtt
!= timeout
) {
long timedelta
= maxrtt
+ (maxrtt
>> 1);
if (timedelta
> timeout
) {
if ((timeout
= timedelta
) > MAXTIME
)
timeout
-= (timeout
- timedelta
) >> 1;
"adjusted timeout to %g seconds(1)\n",
for (r
= RHead
-> r_forw
; r
!= RHead
; r
= r
-> r_forw
) {
for (u
= r
-> r_forw
; u
!= RHead
; u
= u
-> r_forw
)
if (!u
-> r_info
&& u
-> r_lastime
< r
-> r_lastime
)
for (t
= THead
-> t_forw
; t
!= THead
; t
= t
-> t_forw
) {
for (s
= t
-> t_forw
; s
!= THead
; s
= s
-> t_forw
)
if (!s
-> t_info
&& s
-> t_lastime
< t
-> t_lastime
)
if (i
== NULL
|| t
-> t_lastime
< i
-> i_lastime
)
if (i
&& i
-> i_lastime
+ timeout
< timenow
) {
if (++i
-> i_retries
> MAXTRIES
) {
advise (NULLCP
, "too many retries (%d)", MAXTRIES
);
if (pe2ps (ps
, i
-> i_pe
) == NOTOK
) {
advise (NULLCP
, "pe2ps: %s", ps_error (ps
-> ps_errno
));
fprintf (stdout
, "retry ID %d\n", i
-> i_rid
);
(void) print_SNMP_Message (i
-> i_pe
, 1, NULLIP
, NULLVP
, NULLCP
);
"retry ID %d, time now %u, waiting %u, timeout %u\n",
i
-> i_rid
, timenow
, timenow
- i
-> i_lastime
,
i
-> i_lastime
= timenow
;
i
-> i_curinvokes
= currequests
? currequests
: 1;
static print_bulk (bl
, vb
, partial
)
struct type_SNMP_VarBindList
*vb
;
register struct binding
*bv
,
printf ("partial results only...\n");
for (bv
= bl
; bv
; bv
= bv
-> b_next
) {
char *cp
= sprintoid (bv
-> b_name
);
if (i
< (j
= strlen (cp
)))
printf ("%-*s", i
, "row");
for (; vb
; vb
= vb
-> next
)
printf ("\t%s", oid2ode (vb
-> VarBind
-> name
));
for (bv
= bl
; bv
; bv
= bz
) {
register struct binding
*bp
,
printf ("\n%-*s", i
, sprintoid (bv
-> b_name
));
for (bp
= bv
-> b_cols
; bp
; bp
= bq
) {
if ((oi
= name2inst (bp
-> b_name
)) == NULL
|| (os
= oi
-> oi_type
-> ot_syntax
) == NULL
|| (*os
-> os_decode
) (&value
, bp
-> b_value
) == NOTOK
)
vunknown (bp
-> b_value
);
(*os
-> os_print
) (value
, os
);
(*os
-> os_free
) (value
);
static struct type_SNMP_Message
*new_message (arg
, vb
, community
, next
)
struct type_SNMP_VarBindList
*vb
;
register struct type_SNMP_Message
*msg
;
register struct type_SNMP_PDUs
*pdu
;
register struct type_SNMP_PDU
*parm
;
register struct type_SNMP_VarBindList
**vp
;
if ((msg
= (struct type_SNMP_Message
*) calloc (1, sizeof *msg
)) == NULL
)
adios (NULLCP
, "out of memory");
msg
-> version
= int_SNMP_version_version__1
;
if ((msg
-> community
= str2qb (community
, strlen (community
), 1)) == NULL
)
adios (NULLCP
, "out of memory");
if ((pdu
= (struct type_SNMP_PDUs
*) calloc (1, sizeof *pdu
)) == NULL
)
adios (NULLCP
, "out of memory");
pdu
-> offset
= next
? type_SNMP_PDUs_get__next__request
: type_SNMP_PDUs_get__request
;
/* for now, always a PDU... */
if ((parm
= (struct type_SNMP_PDU
*) calloc (1, sizeof *parm
)) == NULL
)
adios (NULLCP
, "out of memory");
pdu
-> un
.get__request
= parm
;
for (vp
= &parm
-> variable__bindings
; vb
; vb
= vb
-> next
) {
register struct type_SNMP_VarBindList
*bind
;
register struct type_SNMP_VarBind
*v
;
if ((bind
= (struct type_SNMP_VarBindList
*) calloc (1, sizeof *bind
))
adios (NULLCP
, "out of memory");
*vp
= bind
, vp
= &bind
-> next
;
if ((v
= (struct type_SNMP_VarBind
*) calloc (1, sizeof *v
)) == NULL
)
adios (NULLCP
, "out of memory");
v
-> name
= oid_copy (arg
);
bcopy ((char *) vb
-> VarBind
-> name
-> oid_elements
,
(char *) v
-> name
-> oid_elements
,
vb
-> VarBind
-> name
-> oid_nelem
* sizeof *v
-> name
-> oid_elements
);
if ((v
-> value
= pe_alloc (PE_CLASS_UNIV
, PE_FORM_PRIM
, PE_PRIM_NULL
))
adios (NULLCP
, "out of memory");
static int new_thread (ps
, vb
, community
, start
, stop
)
struct type_SNMP_VarBindList
*vb
;
register struct thread
*t
;
t
= (struct thread
*) calloc (1, sizeof *t
);
adios (NULLCP
, "new_thread: out of memory");
t
-> t_mid
= (last_id
+= MAXSPACE
);
t
-> t_lo
= oid_copy (start
);
t
-> t_arg
= oid_copy (start
);
t
-> t_hi
= oid_copy (stop
);
t
-> t_msg
= new_message (t
-> t_arg
, vb
, community
, 1);
THead
-> t_forw
= THead
-> t_back
= THead
;
RHead
-> r_forw
= RHead
-> r_back
= RHead
;
insque (t
, THead
-> t_back
);
return next_thread (t
, ps
, 1);
static int new_string (ps
, vb
, community
, bp
)
struct type_SNMP_VarBindList
*vb
;
register struct thread
*t
;
t
= (struct thread
*) calloc (1, sizeof *t
);
adios (NULLCP
, "new_thread: out of memory");
t
-> t_mid
= (last_id
+= MAXSPACE
);
t
-> t_msg
= new_message (bp
-> b_cols
-> b_name
, vb
, community
, 0);
insque (t
, THead
-> t_back
);
return next_thread (t
, ps
, 0);
register struct thread
*t
;
if (debug
&& t
-> t_lo
) {
fprintf (stderr
, "thread from %s to ", oid2ode (t
-> t_lo
));
fprintf (stderr
, "%s did %d get-nexts\n", oid2ode (t
-> t_hi
),
free_SNMP_Message (t
-> t_msg
);
static int next_thread (t
, ps
, next
)
register struct thread
*t
;
if (++t
-> t_rid
>= t
-> t_mid
)
t
-> t_rid
= t
-> t_mid
- MAXSPACE
;
t
-> t_msg
-> data
-> offset
=
next
? type_SNMP_PDUs_get__next__request
: type_SNMP_PDUs_get__request
;
t
-> t_msg
-> data
-> un
.get__response
-> request__id
= t
-> t_rid
;
pe_free (t
-> t_pe
), t
-> t_pe
= NULL
;
if (encode_SNMP_Message (&t
-> t_pe
, 1, 0, NULLCP
, t
-> t_msg
) == NOTOK
) {
advise (NULLCP
, "encode_SNMP_Message: %s", PY_pepy
);
if (pe2ps (ps
, t
-> t_pe
) == NOTOK
) {
advise (NULLCP
, "pe2ps: %s", ps_error (ps
-> ps_errno
));
fprintf (stdout
, "write PDU\n");
(void) print_SNMP_Message (t
-> t_pe
, 1, NULLIP
, NULLVP
, NULLCP
);
t
-> t_lastime
= timenow
;
t
-> t_curinvokes
= curthreads
? curthreads
: 1;
bulk2 (ps
, sd
, vb
, community
)
register struct type_SNMP_VarBindList
*vb
;
register struct request
*r
;
register struct binding
**bp
;
timemin
= timemax
= timeout
;
currequests
= maxrequests
= totbounds
= maxbounds
= dedrequests
= 0;
threadlimit
= MAXTHREADS
;
totreqs
= totretr
= totrsps
= totdups
= 0;
(void) gettimeofday (&tvs
, (struct timezone
*) 0);
timenow
= tvs
.tv_sec
* 1000L + tvs
.tv_usec
/ 1000L;
a
= oid_copy (arg
= vb
-> VarBind
-> name
);
a
-> oid_elements
[a
-> oid_nelem
++] = 127;
new_bound (community
, arg
, a
);
b
-> oid_elements
[b
-> oid_nelem
++] = 192;
new_bound (community
, a
, b
);
a
-> oid_elements
[(--a
-> oid_nelem
) - 1]++;
new_bound (community
, b
, a
);
if (push_requests (ps
, community
, 0) == NOTOK
)
bp
= &bl
, bl
= NULL
, rows
= 0;
for (timelap
= 0; RHead
-> r_forw
!= RHead
; timelap
++) {
if ((backoff
= wait_for_action (sd
, ps
)) == NOTOK
)
for (r
= RHead
-> r_forw
; r
!= RHead
; r
= u
) {
register struct bound
*br
,
register struct type_SNMP_VarBindList
*vr
,
vv
= &r
-> r_msg
-> data
-> un
.get__request
-> variable__bindings
;
register struct binding
*bv
,
if ((vr
= *vv
) == NULL
) {
"missing variable in response, continuing");
if (oid_cmp (br
-> r_arg
, b
= vr
-> VarBind
-> name
) >= 0) {
(void) strcpy (buffer
, oid2ode (br
-> r_arg
));
"agent botched get-next (%s -> %s), continuing",
if (oid_cmp (b
, br
-> r_hi
) >= 0) {
free_SNMP_VarBindList (vr
);
br
-> r_arg
= oid_copy (b
);
oids
.oid_nelem
= b
-> oid_nelem
- arg
-> oid_nelem
;
oids
.oid_elements
= b
-> oid_elements
+ arg
-> oid_nelem
;
if ((bv
= (struct binding
*) calloc (1, sizeof *bv
)) == NULL
)
adios (NULLCP
, "out of memory");
*bp
= bv
, bp
= &bv
-> b_next
;
bv
-> b_name
= oid_copy (&oids
);
if ((bv2
= (struct binding
*) calloc (1, sizeof *bv2
)) == NULL
)
adios (NULLCP
, "out of memory");
bv2
-> b_name
= oid_copy (b
);
bv2
-> b_value
= vr
-> VarBind
-> value
;
if ((vr
-> VarBind
-> value
= pe_alloc (PE_CLASS_UNIV
,
adios (NULLCP
, "out of memory");
bb
= &br
-> r_next
, vv
= &vr
-> next
;
advise (NULLCP
, "too many variables in response");
free_SNMP_VarBindList (vr
);
if (timelap
>= SETTLETIME
&& evalreq
< 0 && boundlimit
!= MINBOUNDS
)
if (push_requests (ps
, community
,
currequests
< threadlimit
&& !backoff
) == NOTOK
)
if (bulk2_aux (ps
, sd
, bl
, vb
, community
) == NOTOK
) {
advise (NULLCP
, "aborting bulk retrieval...");
while ((r
= RHead
-> r_forw
) != RHead
)
(void) gettimeofday (&now
, (struct timezone
*) 0);
now
.tv_sec
-= tvs
.tv_sec
;
if ((now
.tv_usec
-= tvs
.tv_usec
) < 0)
now
.tv_sec
--, now
.tv_usec
+= 1000000;
"%d row%s retrieved in %d.%06d seconds during %d/%d iterations",
rows
, rows
!= 1 ? "s" : "", now
.tv_sec
, now
.tv_usec
, timelap
,
advise (NULLCP
, "requests: at most %d active", maxrequests
);
"bounds: %d created, at most %d active, %d integral, %d did nothing",
totbounds
, maxbounds
, boundlimit
, nilbounds
);
"threads: at most %d active, total of %d created",
advise (NULLCP
, "messages: %d request%s sent, along with %d retr%s",
totreqs
, totreqs
!= 1 ? "s" : "", totretr
,
totretr
!= 1 ? "ies" : "y");
advise (NULLCP
, " %d response%s rcvd, along with %d duplicate%s",
totrsps
, totrsps
!= 1 ? "s" : "", totdups
,
totdups
!= 1 ? "s" : "");
advise (NULLCP
, "timeouts: min=%d.%03d fin=%d.%03d max=%d.%03d seconds",
timemin
/ 1000, timemin
% 1000, timeout
/ 1000, timeout
% 1000,
timemax
/ 1000, timemax
% 1000);
print_bulk (bl
, vb
, dedrequests
|| dedthreads
);
static int bulk2_aux (ps
, sd
, bl
, vb
, community
)
register struct type_SNMP_VarBindList
*vb
;
register struct thread
*t
;
curthreads
= maxthreads
= tothreads
= nilthreads
= dedthreads
= 0;
if (bl
== NULL
|| (vb
= vb
-> next
) == NULL
)
if (curthreads
< threadlimit
) {
if (new_string (ps
, vb
, community
, bl
) == NOTOK
)
for (; THead
-> t_forw
!= THead
; timelap2
++) {
if ((backoff
= wait_for_action (sd
, ps
)) == NOTOK
)
for (t
= THead
-> t_forw
; t
!= THead
; t
= u
) {
register struct binding
*bv
,
register struct type_SNMP_VarBindList
*vp
;
bz
= &bv
-> b_cols
-> b_next
;
for (vp
= t
-> t_msg
-> data
-> un
.get__response
if ((bv
= (struct binding
*) calloc (1, sizeof *bv
)) == NULL
)
adios (NULLCP
, "out of memory");
*bz
= bv
, bz
= &bv
-> b_next
;
bv
-> b_name
= oid_copy (vp
-> VarBind
-> name
);
bv
-> b_value
= vp
-> VarBind
-> value
;
if ((vp
-> VarBind
-> value
= pe_alloc (PE_CLASS_UNIV
,
adios (NULLCP
, "out of memory");
if (curthreads
< threadlimit
&& !backoff
&& bl
) {
if (new_string (ps
, vb
, community
, bl
) == NOTOK
)
if (new_string (ps
, vb
, community
, bl
) == NOTOK
)
while ((t
= THead
-> t_forw
) != THead
)
static struct request
*new_request (community
)
register struct request
*r
;
r
= (struct request
*) calloc (1, sizeof *r
);
adios (NULLCP
, "new_request: out of memory");
r
-> r_mid
= (last_id
+= MAXSPACE
);
r
-> r_msg
= new_message (NULLOID
, (struct type_SNMP_VarBindList
*) NULL
,
insque (r
, RHead
-> r_back
);
register struct request
*r
;
register struct bound
*bp
,
for (bp
= r
-> r_bounds
; bp
; bp
= bq
) {
free_SNMP_Message (r
-> r_msg
);
static int new_bound (community
, start
, stop
)
register struct request
*r
;
register struct bound
*b
;
register struct type_SNMP_VarBindList
*vb
;
register struct type_SNMP_VarBind
*v
;
THead
-> t_forw
= THead
-> t_back
= THead
;
RHead
-> r_forw
= RHead
-> r_back
= RHead
;
if ((r
= RHead
-> r_forw
) == RHead
)
r
= new_request (community
);
if ((b
= (struct bound
*) calloc (1, sizeof *b
)) == NULL
)
adios (NULLCP
, "new_bound: out of memory");
b
-> r_next
= r
-> r_bounds
, r
-> r_bounds
= b
;
b
-> r_lo
= oid_copy (start
);
b
-> r_arg
= oid_copy (start
);
b
-> r_hi
= oid_copy (stop
);
if ((vb
= (struct type_SNMP_VarBindList
*) calloc (1, sizeof *vb
)) == NULL
)
adios (NULLCP
, "new_bound: out of memory");
vb
-> next
= r
-> r_msg
-> data
-> un
.get__request
-> variable__bindings
,
r
-> r_msg
-> data
-> un
.get__request
-> variable__bindings
= vb
;
if ((v
= (struct type_SNMP_VarBind
*) calloc (1, sizeof *v
)) == NULL
)
adios (NULLCP
, "new_bound: out of memory");
v
-> name
= oid_copy (start
);
if ((v
-> value
= pe_alloc (PE_CLASS_UNIV
, PE_FORM_PRIM
, PE_PRIM_NULL
))
adios (NULLCP
, "new_bound: out of memory");
register struct bound
*b
;
if (debug
&& b
-> r_lo
) {
fprintf (stderr
, "%d get-nexts on bound: %s to",
b
-> b_gns
, oid2ode (b
-> r_lo
));
fprintf (stderr
, " %s\n", oid2ode (b
-> r_hi
));
static push_requests (ps
, community
, onemore
)
register struct request
*r
;
register struct bound
*bn
,
register struct type_SNMP_VarBindList
*vz
,
struct type_SNMP_VarBindList
*v
;
nrequest
= nbound
= tbound
= 0;
for (r
= RHead
-> r_forw
; r
!= RHead
; r
= r
-> r_forw
) {
if (*bp
= r
-> r_bounds
) {
for (bz
= *bp
; bz
; bz
= bz
-> r_next
)
if (bz
-> r_next
== NULL
)
if (*vp
= r
-> r_msg
-> data
-> un
.get__request
-> variable__bindings
){
for (vz
= *vp
; vz
; vz
= vz
-> next
)
r
-> r_msg
-> data
-> un
.get__request
-> variable__bindings
= NULL
;
if ((tbound
+= nbound
) > maxbounds
)
if ((new = (nbound
+ (boundlimit
- 1)) / boundlimit
- nrequest
) <= 0
for (; new-- > 0; nrequest
++)
(void) new_request (community
);
if ((new = nrequest
* boundlimit
) > (wen
= nbound
<< 1))
for (new -= nbound
, bn
= b
; (new > 0) && bn
; new--, bn
= bn
-> r_next
) {
if ((mid
= oid_median (bn
-> r_arg
, bn
-> r_hi
)) == NULLOID
)
if ((bz
= (struct bound
*) calloc (1, sizeof *bz
)) == NULL
)
adios (NULLCP
, "push_requests: out of memory");
*bp
= bz
, bp
= &bz
-> r_next
;
bz
-> r_lo
= oid_copy (mid
);
bz
-> r_arg
= oid_copy (mid
);
if ((vz
= (struct type_SNMP_VarBindList
*) calloc (1, sizeof *vz
))
adios (NULLCP
, "push_requests: out of memory");
*vp
= vz
, vp
= &vz
-> next
;
if ((vz
-> VarBind
= (struct type_SNMP_VarBind
*)
calloc (1, sizeof *v
)) == NULL
)
adios (NULLCP
, "push_requests: out of memory");
vz
-> VarBind
-> name
= oid_copy (mid
);
if ((vz
-> VarBind
-> value
= pe_alloc (PE_CLASS_UNIV
, PE_FORM_PRIM
,
adios (NULLCP
, "push_requests: out of memory");
for (r
= RHead
-> r_forw
; r
!= RHead
; r
= r
-> r_forw
) {
register struct bound
**inb
;
register struct type_SNMP_VarBindList
**inv
;
inv
= &r
-> r_msg
-> data
-> un
.get__request
-> variable__bindings
;
for (i
= boundlimit
; i
> 0; i
--) {
bz
= b
-> r_next
, vz
= v
-> next
;
*inb
= b
, inb
= &b
-> r_next
, b
-> r_next
= NULL
;
*inv
= v
, inv
= &v
-> next
, v
-> next
= NULL
;
/* should never get here, since we should run out bounds before
running out of requests; if we do ... ?? */
fprintf (stderr
, "push_requests: possibly loss of bounds\n");
for (r
= RHead
-> r_forw
; r
!= RHead
; r
= u
) {
if (r
-> r_nbound
<= 0) {
if (++r
-> r_rid
>= r
-> r_mid
)
r
-> r_rid
= r
-> r_mid
- MAXSPACE
;
r
-> r_msg
-> data
-> offset
= type_SNMP_PDUs_get__next__request
;
r
-> r_msg
-> data
-> un
.get__response
-> request__id
= r
-> r_rid
;
pe_free (r
-> r_pe
), r
-> r_pe
= NULL
;
if (encode_SNMP_Message (&r
-> r_pe
, 1, 0, NULLCP
, r
-> r_msg
)
advise (NULLCP
, "encode_SNMP_Message: %s", PY_pepy
);
if (pe2ps (ps
, r
-> r_pe
) == NOTOK
) {
advise (NULLCP
, "pe2ps: %s", ps_error (ps
-> ps_errno
));
fprintf (stdout
, "write PDU\n");
(void) print_SNMP_Message (r
-> r_pe
, 1, NULLIP
, NULLVP
, NULLCP
);
r
-> r_lastime
= timenow
;
r
-> r_curinvokes
= currequests
? currequests
: 1;
static OID
oid_median (a
, b
)
register unsigned int *ap
,
if (oid_cmp (a
, b
) >= 0) {
(void) strcpy (buffer
, sprintoid (a
));
adios (NULLCP
, "oid_median(%s <= %s)", buffer
, sprintoid (b
));
for (i
= 1, ap
= a
-> oid_elements
, bp
= b
-> oid_elements
;
if (i
> a
-> oid_nelem
) {
for (; *bp
== NULL
; bp
++)
if (++i
> b
-> oid_nelem
)
c
-> oid_elements
[(c
-> oid_nelem
= i
) - 1] = *bp
>> 1;
if ((c
-> oid_elements
[(c
-> oid_nelem
= i
) - 1] =
*ap
+ ((*bp
- *ap
) >> 1))
bp
= &c
-> oid_elements
[c
-> oid_nelem
++];
if (++i
>= a
-> oid_nelem
) {
*bp
= *ap
>= 16383 ? *ap
+ 16383
: *ap
>= 4095 ? *ap
+ 4095
: *ap
>= 1023 ? *ap
+ 1023
c
-> oid_elements
[c
-> oid_nelem
++] = 0;
(void) strcpy (buffer
, sprintoid (a
));
fprintf (stderr
, "oid_median(%s, %s) fails",
if (oid_cmp (a
, c
) >= 0) {
(void) strcpy (buf1
, sprintoid (a
));
(void) strcpy (buf2
, sprintoid (b
));
adios (NULLCP
, "oid_median(%s, %s) -> %s loses(1)",
buf1
, buf2
, sprintoid (c
));
if (oid_cmp (c
, b
) >= 0) {
(void) strcpy (buf1
, sprintoid (a
));
(void) strcpy (buf2
, sprintoid (b
));
adios (NULLCP
, "oid_median(%s, %s) -> %s loses(2)",
buf1
, buf2
, sprintoid (c
));
if ((b
= oid_cpy (a
)) == NULL
)
adios (NULLCP
, "oid_copy: out of memory");