4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
41 #include <sys/types.h>
48 * Buffer and line limits
50 #define SNMP_DBLOCK_SZ 4096
51 #define SNMP_DMAX_LINE 80
52 #define SNMP_NCHARS_IN_A_ROW 16
57 #define SNMP_DEBUG_CMD 0x01
58 #define SNMP_DEBUG_VAR 0x02
59 #define SNMP_DEBUG_PDU 0x04
60 #define SNMP_DEBUG_ASN 0x08
61 #define SNMP_DEBUG_PKT 0x10
62 #define SNMP_DEBUG_IO 0x20
64 #define SNMP_DEBUG_DEFAULT 0x15 /* cmd, pdu, pkt */
65 #define SNMP_DEBUG_EXTENDED 0x35 /* cmd, pdu, pkt, io */
66 #define SNMP_DEBUG_ALL 0x3f
71 #define SNMP_DCMD_INDENT 2
72 #define SNMP_DVAR_INDENT 4
73 #define SNMP_DPDU_INDENT 6
74 #define SNMP_DASN_INDENT 8
75 #define SNMP_DPKT_INDENT 10
76 #define SNMP_DIO_INDENT 12
78 #define SNMP_DHDR_PREFIX (const char *)" ___ "
79 #define SNMP_DHDR_SUFFIX (const char *)" ___"
80 #define SNMP_DTEXT_PREFIX (const char *)"| "
83 * All debug vars are protected by a single lock
85 static mutex_t snmp_dbuf_lock
; /* debug lock */
86 static uint16_t snmp_debug_flag
= SNMP_DEBUG_EXTENDED
; /* debug flags */
87 static char *snmp_dbuf
= NULL
; /* the debug buffer */
88 static char *snmp_dbuf_curp
= NULL
; /* current dbuf index */
89 static char *snmp_dbuf_tail
= NULL
; /* current dbuf tail */
90 static int snmp_dbuf_sz
= 0; /* current dbuf size */
91 static int snmp_dbuf_overflow
= 0; /* no more memory */
92 static char snmp_lbuf
[SNMP_DMAX_LINE
]; /* scratch space */
102 static snmp_key_to_str_t snmp_cmds
[] = {
103 { SNMP_MSG_GET
, "SNMP_MSG_GET" },
104 { SNMP_MSG_GETNEXT
, "SNMP_MSG_GETNEXT" },
105 { SNMP_MSG_RESPONSE
, "SNMP_MSG_RESPONSE" },
106 { SNMP_MSG_SET
, "SNMP_MSG_SET" },
107 { SNMP_MSG_TRAP
, "SNMP_MSG_TRAP" },
108 { SNMP_MSG_GETBULK
, "SNMP_MSG_GETBULK" },
109 { SNMP_MSG_INFORM
, "SNMP_MSG_INFORM" },
110 { SNMP_MSG_TRAP2
, "SNMP_MSG_TRAP2" },
111 { SNMP_MSG_REPORT
, "SNMP_MSG_REPORT" }
114 static snmp_key_to_str_t snmp_vartypes
[] = {
115 { ASN_BOOLEAN
, "ASN_BOOLEAN" },
116 { ASN_INTEGER
, "ASN_INTEGER" },
117 { ASN_BIT_STR
, "ASN_BIT_STR" },
118 { ASN_OCTET_STR
, "ASN_OCTET_STR" },
119 { ASN_NULL
, "ASN_NULL" },
120 { ASN_OBJECT_ID
, "ASN_OBJECT_ID" },
121 { ASN_SEQUENCE
, "ASN_SEQUENCE" }
124 static snmp_key_to_str_t snmp_asnencodings
[] = {
125 { SNMP_DASN_SEQUENCE
, "ASN SEQUENCE" },
126 { SNMP_DASN_LENGTH
, "ASN LENGTH" },
127 { SNMP_DASN_INT
, "ASN INT" },
128 { SNMP_DASN_OCTET_STR
, "ASN OCTET STR" },
129 { SNMP_DASN_OID
, "ASN OBJECT ID" },
130 { SNMP_DASN_NULL
, "ASN NULL" }
133 static char *debug_tags
[] = {
134 "SNMP Command Request",
147 static const int n_tags
= sizeof (debug_tags
) / sizeof (char *);
152 static char *snmp_cmdstr_lookup(int cmd
);
153 static char *snmp_vtypestr_lookup(int vtype
);
154 static char *snmp_asnencoding_lookup(int asnkey
);
155 static void snmp_get_dumpchars(uchar_t
*abuf
, uchar_t
*p
, int nchars
);
156 static void snmp_log_append(char *bufp
);
157 static void snmp_dbuf_realloc(void);
160 snmp_debug_init(void)
162 (void) mutex_init(&snmp_dbuf_lock
, USYNC_THREAD
, NULL
);
164 (void) mutex_lock(&snmp_dbuf_lock
);
166 if (snmp_dbuf
== NULL
)
167 snmp_debug_flag
= 0; /* really tragic */
168 (void) mutex_unlock(&snmp_dbuf_lock
);
172 snmp_log_cmd(uint_t tag
, int cmd
, int n_oids
, char *oidstr
, int row
)
180 (void) mutex_lock(&snmp_dbuf_lock
);
182 if ((snmp_debug_flag
& SNMP_DEBUG_CMD
) == 0) {
183 (void) mutex_unlock(&snmp_dbuf_lock
);
187 snmp_log_append("\n");
190 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%s%s%s\n",
191 SNMP_DCMD_INDENT
, ' ', SNMP_DHDR_PREFIX
,
192 debug_tags
[tag
], SNMP_DHDR_SUFFIX
);
193 snmp_log_append(snmp_lbuf
);
196 if ((cmdstr
= snmp_cmdstr_lookup(cmd
)) == NULL
) {
197 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%sCMD=%#x\n",
198 SNMP_DCMD_INDENT
, ' ', SNMP_DTEXT_PREFIX
, cmd
);
200 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%s%s\n",
201 SNMP_DCMD_INDENT
, ' ', SNMP_DTEXT_PREFIX
, cmdstr
);
203 snmp_log_append(snmp_lbuf
);
205 for (i
= 0; i
< n_oids
; i
++) {
206 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%s %s.%d\n",
207 SNMP_DCMD_INDENT
, ' ', SNMP_DTEXT_PREFIX
,
209 snmp_log_append(snmp_lbuf
);
211 oidstr
+= strlen(oidstr
) + 1;
214 (void) mutex_unlock(&snmp_dbuf_lock
);
218 snmp_log_var(uint_t tag
, pdu_varlist_t
*vp
)
225 (void) mutex_lock(&snmp_dbuf_lock
);
227 if ((snmp_debug_flag
& SNMP_DEBUG_VAR
) == 0) {
228 (void) mutex_unlock(&snmp_dbuf_lock
);
232 snmp_log_append("\n");
235 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%s%s%s\n",
236 SNMP_DVAR_INDENT
, ' ', SNMP_DHDR_PREFIX
,
237 debug_tags
[tag
], SNMP_DHDR_SUFFIX
);
238 snmp_log_append(snmp_lbuf
);
241 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%snextvar = %#x\n",
242 SNMP_DVAR_INDENT
, ' ', SNMP_DTEXT_PREFIX
, vp
->nextvar
);
243 snmp_log_append(snmp_lbuf
);
245 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%sname = %#x\n",
246 SNMP_DVAR_INDENT
, ' ', SNMP_DTEXT_PREFIX
, vp
->name
);
247 snmp_log_append(snmp_lbuf
);
249 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%sname_len = %u\n",
250 SNMP_DVAR_INDENT
, ' ', SNMP_DTEXT_PREFIX
, vp
->name_len
);
251 snmp_log_append(snmp_lbuf
);
253 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%sval.ptr = %#x\n",
254 SNMP_DVAR_INDENT
, ' ', SNMP_DTEXT_PREFIX
, vp
->val
.str
);
255 snmp_log_append(snmp_lbuf
);
257 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%sval_len = %u\n",
258 SNMP_DVAR_INDENT
, ' ', SNMP_DTEXT_PREFIX
, vp
->val_len
);
259 snmp_log_append(snmp_lbuf
);
261 if ((vts
= snmp_vtypestr_lookup(vp
->type
)) == NULL
) {
262 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%stype = %#x\n",
263 SNMP_DVAR_INDENT
, ' ', SNMP_DTEXT_PREFIX
, vp
->type
);
265 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%stype = %s\n",
266 SNMP_DVAR_INDENT
, ' ', SNMP_DTEXT_PREFIX
, vts
);
268 snmp_log_append(snmp_lbuf
);
270 (void) mutex_unlock(&snmp_dbuf_lock
);
274 snmp_log_pdu(uint_t tag
, snmp_pdu_t
*pdu
)
281 (void) mutex_lock(&snmp_dbuf_lock
);
283 if ((snmp_debug_flag
& SNMP_DEBUG_PDU
) == 0) {
284 (void) mutex_unlock(&snmp_dbuf_lock
);
288 snmp_log_append("\n");
291 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%s%s%s\n",
292 SNMP_DPDU_INDENT
, ' ', SNMP_DHDR_PREFIX
,
293 debug_tags
[tag
], SNMP_DHDR_SUFFIX
);
294 snmp_log_append(snmp_lbuf
);
297 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%sversion = %d\n",
298 SNMP_DPDU_INDENT
, ' ', SNMP_DTEXT_PREFIX
, pdu
->version
);
299 snmp_log_append(snmp_lbuf
);
301 if (pdu
->community
) {
302 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
,
303 "%*c%scommunity = %s\n", SNMP_DPDU_INDENT
, ' ',
304 SNMP_DTEXT_PREFIX
, pdu
->community
);
306 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
,
307 "%*c%scommunity = %#x\n", SNMP_DPDU_INDENT
, ' ',
308 SNMP_DTEXT_PREFIX
, pdu
->community
);
310 snmp_log_append(snmp_lbuf
);
312 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%scommunity_len = %u\n",
313 SNMP_DPDU_INDENT
, ' ', SNMP_DTEXT_PREFIX
, pdu
->community_len
);
314 snmp_log_append(snmp_lbuf
);
316 if ((cmdstr
= snmp_cmdstr_lookup(pdu
->command
)) == NULL
) {
317 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
,
318 "%*c%scommand = %#x\n", SNMP_DPDU_INDENT
, ' ',
319 SNMP_DTEXT_PREFIX
, pdu
->command
);
321 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
,
322 "%*c%scommand = %s\n", SNMP_DPDU_INDENT
, ' ',
323 SNMP_DTEXT_PREFIX
, cmdstr
);
325 snmp_log_append(snmp_lbuf
);
327 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%sreqid = %d\n",
328 SNMP_DPDU_INDENT
, ' ', SNMP_DTEXT_PREFIX
, pdu
->reqid
);
329 snmp_log_append(snmp_lbuf
);
331 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
,
332 "%*c%serrstat = %#x (non-repeaters)\n", SNMP_DPDU_INDENT
, ' ',
333 SNMP_DTEXT_PREFIX
, pdu
->errstat
);
334 snmp_log_append(snmp_lbuf
);
336 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
,
337 "%*c%serrindex = %u (max-reps)\n", SNMP_DPDU_INDENT
, ' ',
338 SNMP_DTEXT_PREFIX
, pdu
->errindex
);
339 snmp_log_append(snmp_lbuf
);
341 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%svars = %#x\n",
342 SNMP_DPDU_INDENT
, ' ', SNMP_DTEXT_PREFIX
, pdu
->vars
);
343 snmp_log_append(snmp_lbuf
);
345 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%sreq_pkt = %#x\n",
346 SNMP_DPDU_INDENT
, ' ', SNMP_DTEXT_PREFIX
, pdu
->req_pkt
);
347 snmp_log_append(snmp_lbuf
);
349 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%sreq_pktsz = %u\n",
350 SNMP_DPDU_INDENT
, ' ', SNMP_DTEXT_PREFIX
, pdu
->req_pktsz
);
351 snmp_log_append(snmp_lbuf
);
353 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%sreply_pkt = %#x\n",
354 SNMP_DPDU_INDENT
, ' ', SNMP_DTEXT_PREFIX
, pdu
->reply_pkt
);
355 snmp_log_append(snmp_lbuf
);
357 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%sreply_pktsz = %u\n",
358 SNMP_DPDU_INDENT
, ' ', SNMP_DTEXT_PREFIX
, pdu
->reply_pktsz
);
359 snmp_log_append(snmp_lbuf
);
361 snmp_log_append("\n");
363 (void) mutex_unlock(&snmp_dbuf_lock
);
367 snmp_log_asn(int key
, uchar_t
*pkt
, size_t pktsz
)
376 (void) mutex_lock(&snmp_dbuf_lock
);
378 if ((snmp_debug_flag
& SNMP_DEBUG_ASN
) == 0) {
379 (void) mutex_unlock(&snmp_dbuf_lock
);
383 if ((asnstr
= snmp_asnencoding_lookup(key
)) == NULL
) {
384 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%sASNKEY=%#x\n",
385 SNMP_DASN_INDENT
, ' ', SNMP_DTEXT_PREFIX
, key
);
387 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%s%s\n",
388 SNMP_DASN_INDENT
, ' ', SNMP_DTEXT_PREFIX
, asnstr
);
390 snmp_log_append(snmp_lbuf
);
393 for (i
= 0; i
< nrows
; i
++) {
394 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%s "
395 "%02x %02x %02x %02x %02x %02x %02x %02x "
396 "%02x %02x %02x %02x %02x %02x %02x %02x\n",
397 SNMP_DASN_INDENT
, ' ', SNMP_DTEXT_PREFIX
,
398 pkt
[0], pkt
[1], pkt
[2], pkt
[3], pkt
[4], pkt
[5],
399 pkt
[6], pkt
[7], pkt
[8], pkt
[9], pkt
[10], pkt
[11],
400 pkt
[12], pkt
[13], pkt
[14], pkt
[15]);
403 snmp_log_append(snmp_lbuf
);
406 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%s ",
407 SNMP_DASN_INDENT
, ' ', SNMP_DTEXT_PREFIX
);
409 p
= snmp_lbuf
+ SNMP_DASN_INDENT
+ strlen(SNMP_DTEXT_PREFIX
) + 1;
410 len
= SNMP_DMAX_LINE
- SNMP_DASN_INDENT
- strlen(SNMP_DTEXT_PREFIX
) - 1;
413 for (i
= 0; i
< nrem
; i
++) {
414 (void) snprintf(p
, len
, " %02x", pkt
[i
]);
419 (void) snprintf(p
, len
, "\n");
420 snmp_log_append(snmp_lbuf
);
422 (void) mutex_unlock(&snmp_dbuf_lock
);
426 snmp_log_pkt(uint_t tag
, uchar_t
*pkt
, size_t pktsz
)
428 uchar_t ascii
[SNMP_NCHARS_IN_A_ROW
+ 1];
437 (void) mutex_lock(&snmp_dbuf_lock
);
439 if ((snmp_debug_flag
& SNMP_DEBUG_PKT
) == 0) {
440 (void) mutex_unlock(&snmp_dbuf_lock
);
444 snmp_log_append("\n");
447 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%s%s%s\n",
448 SNMP_DPKT_INDENT
, ' ',
449 SNMP_DHDR_PREFIX
, debug_tags
[tag
], SNMP_DHDR_SUFFIX
);
450 snmp_log_append(snmp_lbuf
);
453 nrows
= pktsz
/ SNMP_NCHARS_IN_A_ROW
;
454 nrem
= pktsz
% SNMP_NCHARS_IN_A_ROW
;
456 for (i
= 0; i
< nrows
; i
++) {
457 snmp_get_dumpchars(ascii
, p
, SNMP_NCHARS_IN_A_ROW
);
458 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%s"
459 "%02x %02x %02x %02x %02x %02x %02x %02x "
460 "%02x %02x %02x %02x %02x %02x %02x %02x "
462 SNMP_DPKT_INDENT
, ' ', SNMP_DTEXT_PREFIX
,
463 p
[0], p
[1], p
[2], p
[3], p
[4], p
[5], p
[6], p
[7],
464 p
[8], p
[9], p
[10], p
[11], p
[12], p
[13], p
[14], p
[15],
468 snmp_log_append(snmp_lbuf
);
471 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
, "%*c%s",
472 SNMP_DPKT_INDENT
, ' ', SNMP_DTEXT_PREFIX
);
474 snmp_get_dumpchars(ascii
, p
, nrem
);
476 bufp
= snmp_lbuf
+ SNMP_DPKT_INDENT
+ strlen(SNMP_DTEXT_PREFIX
);
477 len
= SNMP_DMAX_LINE
- SNMP_DPKT_INDENT
+ strlen(SNMP_DTEXT_PREFIX
);
478 for (i
= 0; i
< 16; i
++) {
480 (void) snprintf(bufp
, len
, "%02x ", p
[i
]);
482 (void) snprintf(bufp
, len
, " ");
487 (void) snprintf(bufp
, len
, "%s\n", ascii
);
488 snmp_log_append(snmp_lbuf
);
490 (void) mutex_unlock(&snmp_dbuf_lock
);
494 snmp_log_io(uint_t tag
, int a1
, uint_t a2
, uint_t a3
)
496 (void) mutex_lock(&snmp_dbuf_lock
);
498 if ((snmp_debug_flag
& SNMP_DEBUG_IO
) == 0) {
499 (void) mutex_unlock(&snmp_dbuf_lock
);
503 snmp_log_append("\n");
506 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
,
507 "%*c%s%s(%d, %#x, %#x)\n", SNMP_DIO_INDENT
, ' ',
508 SNMP_DTEXT_PREFIX
, debug_tags
[tag
], a1
, a2
, a3
);
510 (void) snprintf(snmp_lbuf
, SNMP_DMAX_LINE
,
511 "%*c%s%#x(%d, %#x, %#x)\n", SNMP_DIO_INDENT
, ' ',
512 SNMP_DTEXT_PREFIX
, tag
, a1
, a2
, a3
);
515 snmp_log_append(snmp_lbuf
);
517 (void) mutex_unlock(&snmp_dbuf_lock
);
521 snmp_cmdstr_lookup(int cmd
)
523 int nelem
= sizeof (snmp_cmds
) / sizeof (snmp_key_to_str_t
);
526 for (i
= 0; i
< nelem
; i
++) {
527 if (snmp_cmds
[i
].key
== cmd
)
528 return (snmp_cmds
[i
].str
);
535 snmp_vtypestr_lookup(int vtype
)
537 int nelem
= sizeof (snmp_vartypes
) / sizeof (snmp_key_to_str_t
);
540 for (i
= 0; i
< nelem
; i
++) {
541 if (snmp_vartypes
[i
].key
== vtype
)
542 return (snmp_vartypes
[i
].str
);
549 snmp_asnencoding_lookup(int asnkey
)
551 int nelem
= sizeof (snmp_asnencodings
) / sizeof (snmp_key_to_str_t
);
554 for (i
= 0; i
< nelem
; i
++) {
555 if (snmp_asnencodings
[i
].key
== asnkey
)
556 return (snmp_asnencodings
[i
].str
);
563 snmp_get_dumpchars(uchar_t
*abuf
, uchar_t
*p
, int nchars
)
567 if (nchars
> SNMP_NCHARS_IN_A_ROW
)
568 nchars
= SNMP_NCHARS_IN_A_ROW
;
571 for (i
= 0; i
< nchars
; i
++)
572 abuf
[i
] = isprint(p
[i
]) ? p
[i
] : '.';
576 snmp_log_append(char *bufp
)
581 if ((snmp_dbuf_curp
+ len
) >= snmp_dbuf_tail
)
584 (void) strcpy(snmp_dbuf_curp
, bufp
);
586 snmp_dbuf_curp
+= len
;
590 snmp_dbuf_realloc(void)
596 count
= snmp_dbuf_sz
+ SNMP_DBLOCK_SZ
;
597 if ((p
= (char *)calloc(count
, 1)) == NULL
) {
598 snmp_dbuf_overflow
++;
599 snmp_dbuf_curp
= snmp_dbuf
;
604 offset
= snmp_dbuf_curp
- snmp_dbuf
;
605 (void) memcpy(p
, snmp_dbuf
, snmp_dbuf_sz
);
610 snmp_dbuf_sz
+= SNMP_DBLOCK_SZ
;
612 snmp_dbuf_curp
= snmp_dbuf
+ offset
;
613 snmp_dbuf_tail
= snmp_dbuf
+ snmp_dbuf_sz
;