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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI" /* SVr3.2H */
29 * Dump STREAMS module. Could be used anywhere on a stream to
30 * print all message headers and data on to the console.
33 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/stream.h>
37 #include <sys/stropts.h>
38 #include <sys/errno.h>
39 #include <sys/cmn_err.h>
41 #include <sys/strsun.h>
44 #include <sys/modctl.h>
46 static char hdr
[100]; /* current message header */
47 static char hdrpad
[100]; /* pad of same length as hdr[] */
50 * Raw buffer dumping routine. Displays the contents of the first message in
51 * message chain `mp', using the "traditional" dump format.
53 * For instance, "Hello STREAMS, panicked lately?" would be displayed as:
55 * RD 30001dbb240 M_DATA 48656C6C 6F205354 5245414D 532C2070 Hello STREAMS, p
56 * 616E6963 6B656420 6C617465 6C793F anicked lately?
58 * If the character being displayed is not printable, a '.' is shown.
61 #define DEDUMP_HEXPERBLK 4
62 #define DEDUMP_HEXLEN (sizeof ("11223344") * 4)
63 #define DEDUMP_ASCLEN (sizeof ("0123456789ABCDEF") - 1)
66 dedump_raw(mblk_t
*mp
)
68 char hex
[DEDUMP_HEXLEN
+ 1], asc
[DEDUMP_ASCLEN
+ 1];
69 int hexi
= 0, asci
= 0, i
= 0;
73 hex
[DEDUMP_HEXLEN
] = '\0';
76 if (i
== MBLKL(mp
) || (i
!= 0 && (i
% DEDUMP_ASCLEN
) == 0)) {
78 * We're either out of data or we've filled a complete
79 * line. In either case, print out what we've got --
80 * but first NUL-terminate asc[] and pad out hex[]
84 (void) memset(hex
+ hexi
, ' ', DEDUMP_HEXLEN
- hexi
);
85 (void) printf("%s %s %s\n", hdrp
, hex
, asc
);
88 * If we're out of data, bail. Otherwise, reset asci
89 * and hexi for another lap around. Also, set hdrp to
90 * the pad since we only want to show the header once.
101 hexi
+= snprintf(hex
+ hexi
, 3, "%02X", c
);
102 if ((i
% DEDUMP_HEXPERBLK
) == 0)
104 asc
[asci
++] = (c
>= 32 && c
<= 126) ? c
: '.';
109 dedump_char(mblk_t
*mp
)
111 (void) printf("%s 0x%x\n", hdr
, *(uchar_t
*)mp
->b_rptr
);
115 dedump_int(mblk_t
*mp
)
117 (void) printf("%s %d\n", hdr
, *(int *)mp
->b_rptr
);
121 dedump_ssize(mblk_t
*mp
)
123 (void) printf("%s %ld\n", hdr
, *(ssize_t
*)mp
->b_rptr
);
127 dedump_cmdblk(mblk_t
*mp
)
129 struct cmdblk
*cbp
= (struct cmdblk
*)mp
->b_rptr
;
131 (void) printf("%s cmd %x cred %p len %u error %d\n", hdr
, cbp
->cb_cmd
,
132 (void *)cbp
->cb_cr
, cbp
->cb_len
, cbp
->cb_error
);
136 dedump_iocblk(mblk_t
*mp
)
138 struct iocblk
*ic
= (struct iocblk
*)mp
->b_rptr
;
140 (void) printf("%s cmd %x cred %p id %u flag %x count %ld rval %d "
141 "err %d\n", hdr
, ic
->ioc_cmd
, (void *)ic
->ioc_cr
, ic
->ioc_id
,
142 ic
->ioc_flag
, ic
->ioc_count
, ic
->ioc_rval
, ic
->ioc_error
);
146 dedump_stroptions(mblk_t
*mp
)
148 struct stroptions
*so
= (struct stroptions
*)mp
->b_rptr
;
150 (void) printf("%s flag %x readopt %d wroff %u\n", hdr
,
151 so
->so_flags
, so
->so_readopt
, so
->so_wroff
);
153 (void) printf("%s minpsz %ld maxpsz %ld hiwat %lu lowat %lu\n", hdrpad
,
154 so
->so_minpsz
, so
->so_maxpsz
, so
->so_hiwat
, so
->so_lowat
);
156 (void) printf("%s band %u erropt %u maxblk %ld copyopt %u\n", hdrpad
,
157 so
->so_band
, so
->so_erropt
, so
->so_maxblk
, so
->so_copyopt
);
161 dedump_copyreq(mblk_t
*mp
)
163 struct copyreq
*cq
= (struct copyreq
*)mp
->b_rptr
;
165 (void) printf("%s cmd %x cred %p id %u flag %x priv %p addr %p size "
166 "%lu\n", hdr
, cq
->cq_cmd
, (void *)cq
->cq_cr
, cq
->cq_id
, cq
->cq_flag
,
167 (void *)cq
->cq_private
, (void *)cq
->cq_addr
, cq
->cq_size
);
171 dedump_copyresp(mblk_t
*mp
)
173 struct copyresp
*cp
= (struct copyresp
*)mp
->b_rptr
;
175 (void) printf("%s cmd %x cred %p id %u flag %x priv %p rval %p\n", hdr
,
176 cp
->cp_cmd
, (void *)cp
->cp_cr
, cp
->cp_id
, cp
->cp_flag
,
177 (void *)cp
->cp_private
, (void *)cp
->cp_rval
);
180 typedef struct msgfmt
{
183 void (*m_print
)(mblk_t
*);
186 static msgfmt_t msgfmt
[256] = {
187 { M_DATA
, "M_DATA ", dedump_raw
},
188 { M_PROTO
, "M_PROTO ", dedump_raw
},
189 { M_BREAK
, "M_BREAK ", dedump_raw
},
190 { M_PASSFP
, "M_PASSFP ", dedump_raw
},
191 { M_EVENT
, "M_EVENT ", dedump_raw
},
192 { M_SIG
, "M_SIG ", dedump_char
},
193 { M_DELAY
, "M_DELAY ", dedump_int
},
194 { M_CTL
, "M_CTL ", dedump_raw
},
195 { M_IOCTL
, "M_IOCTL ", dedump_iocblk
},
196 { M_SETOPTS
, "M_SETOPTS ", dedump_stroptions
},
197 { M_RSE
, "M_RSE ", dedump_raw
},
198 { M_IOCACK
, "M_IOCACK ", dedump_iocblk
},
199 { M_IOCNAK
, "M_IOCNAK ", dedump_iocblk
},
200 { M_PCPROTO
, "M_PCPROTO ", dedump_raw
},
201 { M_PCSIG
, "M_PCSIG ", dedump_char
},
202 { M_READ
, "M_READ ", dedump_ssize
},
203 { M_FLUSH
, "M_FLUSH ", dedump_char
},
204 { M_STOP
, "M_STOP ", dedump_raw
},
205 { M_START
, "M_START ", dedump_raw
},
206 { M_HANGUP
, "M_HANGUP ", dedump_raw
},
207 { M_ERROR
, "M_ERROR ", dedump_char
},
208 { M_COPYIN
, "M_COPYIN ", dedump_copyreq
},
209 { M_COPYOUT
, "M_COPYOUT ", dedump_copyreq
},
210 { M_IOCDATA
, "M_IOCDATA ", dedump_copyresp
},
211 { M_PCRSE
, "M_PCRSE ", dedump_raw
},
212 { M_STOPI
, "M_STOPI ", dedump_raw
},
213 { M_STARTI
, "M_STARTI ", dedump_raw
},
214 { M_PCEVENT
, "M_PCEVENT ", dedump_raw
},
215 { M_UNHANGUP
, "M_UNHANGUP", dedump_raw
},
216 { M_CMD
, "M_CMD ", dedump_cmdblk
},
221 dedumpopen(queue_t
*q
, dev_t
*devp
, int oflag
, int sflag
, cred_t
*crp
)
227 return (0); /* already attached */
235 dedumpclose(queue_t
*q
, int flag
, cred_t
*crp
)
242 * Common put procedure for upstream and downstream.
245 dedumpput(queue_t
*q
, mblk_t
*mp
)
247 unsigned char type
= DB_TYPE(mp
);
250 hdrlen
= snprintf(hdr
, sizeof (hdr
), "%s %p %10s ",
251 (q
->q_flag
& QREADR
) ? "RD" : "WR", (void *)q
, msgfmt
[type
].m_desc
);
253 hdrpad
[hdrlen
] = '\0';
254 msgfmt
[type
].m_print(mp
);
255 hdrpad
[hdrlen
] = ' ';
261 struct module_info dedump_minfo
= {
262 0xaaa, "dedump", 0, INFPSZ
, 0, 0
265 struct qinit dedumprinit
= {
266 dedumpput
, NULL
, dedumpopen
, dedumpclose
, NULL
, &dedump_minfo
, NULL
269 struct qinit dedumpwinit
= {
270 dedumpput
, NULL
, NULL
, NULL
, NULL
, &dedump_minfo
, NULL
273 struct streamtab dedumpinfo
= {
274 &dedumprinit
, &dedumpwinit
, NULL
, NULL
,
277 static struct fmodsw fsw
= {
280 D_MP
| D_MTPERMOD
/* just to serialize printfs */
283 static struct modlstrmod modlstrmod
= {
284 &mod_strmodops
, "dump streams module", &fsw
287 static struct modlinkage modlinkage
= {
288 MODREV_1
, &modlstrmod
, NULL
298 * Sort msgfmt[] so that msgfmt[n] describes message type n.
300 for (i
= 255; i
!= 0; i
--) {
302 msgfmt
[i
].m_type
= i
;
303 (void) sprintf(msgfmt
[i
].m_desc
, "M_BOGUS_0x%x", i
);
304 msgfmt
[i
].m_print
= dedump_raw
;
305 if (mf
.m_desc
[0] != 0)
306 msgfmt
[mf
.m_type
] = mf
;
310 * Fill hdrpad[] with as many spaces as will fit.
312 (void) memset(hdrpad
, ' ', sizeof (hdrpad
) - 1);
313 hdrpad
[sizeof (hdrpad
) - 1] = '\0';
315 return (mod_install(&modlinkage
));
321 return (mod_remove(&modlinkage
));
325 _info(struct modinfo
*modinfop
)
327 return (mod_info(&modlinkage
, modinfop
));