/* * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey * Copyright (c) 1996-1999 Wichert Akkerman * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $Id$ */ #include "defs.h" #include #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_SYS_POLL_H #include #endif #ifdef HAVE_STROPTS_H #include #endif #ifdef HAVE_SYS_CONF_H #include #endif #ifdef HAVE_SYS_STREAM_H #include #endif #ifdef HAVE_SYS_TIHDR_H #include #endif #if defined(HAVE_SYS_STREAM_H) || defined(LINUX) || defined(FREEBSD) #ifndef HAVE_STROPTS_H #define RS_HIPRI 1 struct strbuf { int maxlen; /* no. of bytes in buffer */ int len; /* no. of bytes returned */ const char *buf; /* pointer to data */ }; #define MORECTL 1 #define MOREDATA 2 #endif /* !HAVE_STROPTS_H */ #ifdef HAVE_SYS_TIUSER_H #include #include #include #endif /* HAVE_SYS_TIUSER_H */ #ifndef FREEBSD static const struct xlat msgflags[] = { { RS_HIPRI, "RS_HIPRI" }, { 0, NULL }, }; static void printstrbuf(struct tcb *tcp, struct strbuf *sbp, int getting) { if (sbp->maxlen == -1 && getting) tprints("{maxlen=-1}"); else { tprints("{"); if (getting) tprintf("maxlen=%d, ", sbp->maxlen); tprintf("len=%d, buf=", sbp->len); printstr(tcp, (unsigned long) sbp->buf, sbp->len); tprints("}"); } } static void printstrbufarg(struct tcb *tcp, int arg, int getting) { struct strbuf buf; if (arg == 0) tprints("NULL"); else if (umove(tcp, arg, &buf) < 0) tprints("{...}"); else printstrbuf(tcp, &buf, getting); tprints(", "); } int sys_putmsg(struct tcb *tcp) { int i; if (entering(tcp)) { /* fd */ tprintf("%ld, ", tcp->u_arg[0]); /* control and data */ for (i = 1; i < 3; i++) printstrbufarg(tcp, tcp->u_arg[i], 0); /* flags */ printflags(msgflags, tcp->u_arg[3], "RS_???"); } return 0; } #if defined(SPARC) || defined(SPARC64) || defined(SUNOS4) || defined(SVR4) int sys_getmsg(struct tcb *tcp) { int i, flags; if (entering(tcp)) { /* fd */ tprintf("%lu, ", tcp->u_arg[0]); } else { if (syserror(tcp)) { tprintf("%#lx, %#lx, %#lx", tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3]); return 0; } /* control and data */ for (i = 1; i < 3; i++) printstrbufarg(tcp, tcp->u_arg[i], 1); /* pointer to flags */ if (tcp->u_arg[3] == 0) tprints("NULL"); else if (umove(tcp, tcp->u_arg[3], &flags) < 0) tprints("[?]"); else { tprints("["); printflags(msgflags, flags, "RS_???"); tprints("]"); } /* decode return value */ switch (tcp->u_rval) { case MORECTL: tcp->auxstr = "MORECTL"; break; case MORECTL|MOREDATA: tcp->auxstr = "MORECTL|MOREDATA"; break; case MOREDATA: tcp->auxstr = "MORECTL"; break; default: tcp->auxstr = NULL; break; } } return RVAL_HEX | RVAL_STR; } #endif /* SPARC || SPARC64 || SUNOS4 || SVR4 */ #if defined SYS_putpmsg || defined SYS_getpmsg static const struct xlat pmsgflags[] = { #ifdef MSG_HIPRI { MSG_HIPRI, "MSG_HIPRI" }, #endif #ifdef MSG_AND { MSG_ANY, "MSG_ANY" }, #endif #ifdef MSG_BAND { MSG_BAND, "MSG_BAND" }, #endif { 0, NULL }, }; #endif #ifdef SYS_putpmsg int sys_putpmsg(struct tcb *tcp) { int i; if (entering(tcp)) { /* fd */ tprintf("%ld, ", tcp->u_arg[0]); /* control and data */ for (i = 1; i < 3; i++) printstrbufarg(tcp, tcp->u_arg[i], 0); /* band */ tprintf("%ld, ", tcp->u_arg[3]); /* flags */ printflags(pmsgflags, tcp->u_arg[4], "MSG_???"); } return 0; } #endif /* SYS_putpmsg */ #ifdef SYS_getpmsg int sys_getpmsg(struct tcb *tcp) { int i, flags; if (entering(tcp)) { /* fd */ tprintf("%lu, ", tcp->u_arg[0]); } else { if (syserror(tcp)) { tprintf("%#lx, %#lx, %#lx, %#lx", tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3], tcp->u_arg[4]); return 0; } /* control and data */ for (i = 1; i < 3; i++) printstrbufarg(tcp, tcp->u_arg[i], 1); /* pointer to band */ printnum(tcp, tcp->u_arg[3], "%d"); tprints(", "); /* pointer to flags */ if (tcp->u_arg[4] == 0) tprints("NULL"); else if (umove(tcp, tcp->u_arg[4], &flags) < 0) tprints("[?]"); else { tprints("["); printflags(pmsgflags, flags, "MSG_???"); tprints("]"); } /* decode return value */ switch (tcp->u_rval) { case MORECTL: tcp->auxstr = "MORECTL"; break; case MORECTL|MOREDATA: tcp->auxstr = "MORECTL|MOREDATA"; break; case MOREDATA: tcp->auxstr = "MORECTL"; break; default: tcp->auxstr = NULL; break; } } return RVAL_HEX | RVAL_STR; } #endif /* SYS_getpmsg */ #endif /* !FREEBSD */ #ifdef HAVE_SYS_POLL_H static const struct xlat pollflags[] = { #ifdef POLLIN { POLLIN, "POLLIN" }, { POLLPRI, "POLLPRI" }, { POLLOUT, "POLLOUT" }, #ifdef POLLRDNORM { POLLRDNORM, "POLLRDNORM" }, #endif #ifdef POLLWRNORM { POLLWRNORM, "POLLWRNORM" }, #endif #ifdef POLLRDBAND { POLLRDBAND, "POLLRDBAND" }, #endif #ifdef POLLWRBAND { POLLWRBAND, "POLLWRBAND" }, #endif { POLLERR, "POLLERR" }, { POLLHUP, "POLLHUP" }, { POLLNVAL, "POLLNVAL" }, #endif { 0, NULL }, }; static int decode_poll(struct tcb *tcp, long pts) { struct pollfd fds; unsigned nfds; unsigned long size, start, cur, end, abbrev_end; int failed = 0; if (entering(tcp)) { nfds = tcp->u_arg[1]; size = sizeof(fds) * nfds; start = tcp->u_arg[0]; end = start + size; if (nfds == 0 || size / sizeof(fds) != nfds || end < start) { tprintf("%#lx, %d, ", tcp->u_arg[0], nfds); return 0; } if (abbrev(tcp)) { abbrev_end = start + max_strlen * sizeof(fds); if (abbrev_end < start) abbrev_end = end; } else { abbrev_end = end; } tprints("["); for (cur = start; cur < end; cur += sizeof(fds)) { if (cur > start) tprints(", "); if (cur >= abbrev_end) { tprints("..."); break; } if (umoven(tcp, cur, sizeof fds, (char *) &fds) < 0) { tprints("?"); failed = 1; break; } if (fds.fd < 0) { tprintf("{fd=%d}", fds.fd); continue; } tprints("{fd="); printfd(tcp, fds.fd); tprints(", events="); printflags(pollflags, fds.events, "POLL???"); tprints("}"); } tprints("]"); if (failed) tprintf(" %#lx", start); tprintf(", %d, ", nfds); return 0; } else { static char outstr[1024]; char *outptr; #define end_outstr (outstr + sizeof(outstr)) const char *flagstr; if (syserror(tcp)) return 0; if (tcp->u_rval == 0) { tcp->auxstr = "Timeout"; return RVAL_STR; } nfds = tcp->u_arg[1]; size = sizeof(fds) * nfds; start = tcp->u_arg[0]; end = start + size; if (nfds == 0 || size / sizeof(fds) != nfds || end < start) return 0; if (abbrev(tcp)) { abbrev_end = start + max_strlen * sizeof(fds); if (abbrev_end < start) abbrev_end = end; } else { abbrev_end = end; } outptr = outstr; for (cur = start; cur < end; cur += sizeof(fds)) { if (umoven(tcp, cur, sizeof fds, (char *) &fds) < 0) { if (outptr < end_outstr - 2) *outptr++ = '?'; failed = 1; break; } if (!fds.revents) continue; if (outptr == outstr) { *outptr++ = '['; } else { if (outptr < end_outstr - 3) outptr = stpcpy(outptr, ", "); } if (cur >= abbrev_end) { if (outptr < end_outstr - 4) outptr = stpcpy(outptr, "..."); break; } if (outptr < end_outstr - (sizeof("{fd=%d, revents=") + sizeof(int)*3) + 1) outptr += sprintf(outptr, "{fd=%d, revents=", fds.fd); flagstr = sprintflags("", pollflags, fds.revents); if (outptr < end_outstr - (strlen(flagstr) + 2)) { outptr = stpcpy(outptr, flagstr); *outptr++ = '}'; } } if (failed) return 0; if (outptr != outstr /* && outptr < end_outstr - 1 (always true)*/) *outptr++ = ']'; *outptr = '\0'; if (pts) { if (outptr < end_outstr - (10 + TIMESPEC_TEXT_BUFSIZE)) { outptr = stpcpy(outptr, outptr == outstr ? "left " : ", left "); sprint_timespec(outptr, tcp, pts); } } if (outptr == outstr) return 0; tcp->auxstr = outstr; return RVAL_STR; #undef end_outstr } } int sys_poll(struct tcb *tcp) { int rc = decode_poll(tcp, 0); if (entering(tcp)) { #ifdef INFTIM if (tcp->u_arg[2] == INFTIM) tprints("INFTIM"); else #endif tprintf("%ld", tcp->u_arg[2]); } return rc; } #ifdef LINUX int sys_ppoll(struct tcb *tcp) { int rc = decode_poll(tcp, tcp->u_arg[2]); if (entering(tcp)) { print_timespec(tcp, tcp->u_arg[2]); tprints(", "); print_sigset(tcp, tcp->u_arg[3], 0); tprintf(", %lu", tcp->u_arg[4]); } return rc; } #endif #else /* !HAVE_SYS_POLL_H */ int sys_poll(struct tcb *tcp) { return 0; } #endif #if !defined(LINUX) && !defined(FREEBSD) static const struct xlat stream_flush_options[] = { { FLUSHR, "FLUSHR" }, { FLUSHW, "FLUSHW" }, { FLUSHRW, "FLUSHRW" }, #ifdef FLUSHBAND { FLUSHBAND, "FLUSHBAND" }, #endif { 0, NULL }, }; static const struct xlat stream_setsig_flags[] = { { S_INPUT, "S_INPUT" }, { S_HIPRI, "S_HIPRI" }, { S_OUTPUT, "S_OUTPUT" }, { S_MSG, "S_MSG" }, #ifdef S_ERROR { S_ERROR, "S_ERROR" }, #endif #ifdef S_HANGUP { S_HANGUP, "S_HANGUP" }, #endif #ifdef S_RDNORM { S_RDNORM, "S_RDNORM" }, #endif #ifdef S_WRNORM { S_WRNORM, "S_WRNORM" }, #endif #ifdef S_RDBAND { S_RDBAND, "S_RDBAND" }, #endif #ifdef S_WRBAND { S_WRBAND, "S_WRBAND" }, #endif #ifdef S_BANDURG { S_BANDURG, "S_BANDURG" }, #endif { 0, NULL }, }; static const struct xlat stream_read_options[] = { { RNORM, "RNORM" }, { RMSGD, "RMSGD" }, { RMSGN, "RMSGN" }, { 0, NULL }, }; static const struct xlat stream_read_flags[] = { #ifdef RPROTDAT { RPROTDAT, "RPROTDAT" }, #endif #ifdef RPROTDIS { RPROTDIS, "RPROTDIS" }, #endif #ifdef RPROTNORM { RPROTNORM, "RPROTNORM" }, #endif { 0, NULL }, }; #ifndef RMODEMASK #define RMODEMASK (~0) #endif #ifdef I_SWROPT static const struct xlat stream_write_flags[] = { { SNDZERO, "SNDZERO" }, { SNDPIPE, "SNDPIPE" }, { 0, NULL }, }; #endif /* I_SWROPT */ #ifdef I_ATMARK static const struct xlat stream_atmark_options[] = { { ANYMARK, "ANYMARK" }, { LASTMARK, "LASTMARK" }, { 0, NULL }, }; #endif /* I_ATMARK */ #ifdef TI_BIND static const struct xlat transport_user_options[] = { { T_CONN_REQ, "T_CONN_REQ" }, { T_CONN_RES, "T_CONN_RES" }, { T_DISCON_REQ, "T_DISCON_REQ" }, { T_DATA_REQ, "T_DATA_REQ" }, { T_EXDATA_REQ, "T_EXDATA_REQ" }, { T_INFO_REQ, "T_INFO_REQ" }, { T_BIND_REQ, "T_BIND_REQ" }, { T_UNBIND_REQ, "T_UNBIND_REQ" }, { T_UNITDATA_REQ,"T_UNITDATA_REQ"}, { T_OPTMGMT_REQ,"T_OPTMGMT_REQ" }, { T_ORDREL_REQ, "T_ORDREL_REQ" }, { 0, NULL }, }; static const struct xlat transport_user_flags[] = { { 0, "0" }, { T_MORE, "T_MORE" }, { T_EXPEDITED, "T_EXPEDITED" }, { T_NEGOTIATE, "T_NEGOTIATE" }, { T_CHECK, "T_CHECK" }, { T_DEFAULT, "T_DEFAULT" }, { T_SUCCESS, "T_SUCCESS" }, { T_FAILURE, "T_FAILURE" }, { T_CURRENT, "T_CURRENT" }, { T_PARTSUCCESS,"T_PARTSUCCESS" }, { T_READONLY, "T_READONLY" }, { T_NOTSUPPORT, "T_NOTSUPPORT" }, { 0, NULL }, }; #ifdef HAVE_STRUCT_T_OPTHDR static const struct xlat xti_level[] = { { XTI_GENERIC, "XTI_GENERIC" }, { 0, NULL }, }; static const struct xlat xti_generic[] = { { XTI_DEBUG, "XTI_DEBUG" }, { XTI_LINGER, "XTI_LINGER" }, { XTI_RCVBUF, "XTI_RCVBUF" }, { XTI_RCVLOWAT, "XTI_RCVLOWAT" }, { XTI_SNDBUF, "XTI_SNDBUF" }, { XTI_SNDLOWAT, "XTI_SNDLOWAT" }, { 0, NULL }, }; void print_xti_optmgmt(struct tcb *tcp, long addr, int len) { int c = 0; struct t_opthdr hdr; while (len >= (int) sizeof hdr) { if (umove(tcp, addr, &hdr) < 0) break; if (c++) { tprints(", "); } else if (len > hdr.len + sizeof hdr) { tprints("["); } tprints("{level="); printxval(xti_level, hdr.level, "???"); tprints(", name="); switch (hdr.level) { case XTI_GENERIC: printxval(xti_generic, hdr.name, "XTI_???"); break; default: tprintf("%ld", hdr.name); break; } tprints(", status="); printxval(transport_user_flags, hdr.status, "T_???"); addr += sizeof hdr; len -= sizeof hdr; if ((hdr.len -= sizeof hdr) > 0) { if (hdr.len > len) break; tprints(", val="); if (len == sizeof(int)) printnum(tcp, addr, "%d"); else printstr(tcp, addr, hdr.len); addr += hdr.len; len -= hdr.len; } tprints("}"); } if (len > 0) { if (c++) tprints(", "); printstr(tcp, addr, len); } if (c > 1) tprints("]"); } #endif static void print_optmgmt(struct tcb *tcp, long addr, int len) { /* We don't know how to tell if TLI (socket) or XTI optmgmt is being used yet, assume TLI. */ #if defined (HAVE_STRUCT_OPTHDR) print_sock_optmgmt(tcp, addr, len); #elif defined (HAVE_STRUCT_T_OPTHDR) print_xti_optmgmt(tcp, addr, len); #else printstr(tcp, addr, len); #endif } static const struct xlat service_type[] = { { T_COTS, "T_COTS" }, { T_COTS_ORD, "T_COTS_ORD" }, { T_CLTS, "T_CLTS" }, { 0, NULL }, }; static const struct xlat ts_state[] = { { TS_UNBND, "TS_UNBND" }, { TS_WACK_BREQ, "TS_WACK_BREQ" }, { TS_WACK_UREQ, "TS_WACK_UREQ" }, { TS_IDLE, "TS_IDLE" }, { TS_WACK_OPTREQ,"TS_WACK_OPTREQ"}, { TS_WACK_CREQ, "TS_WACK_CREQ" }, { TS_WCON_CREQ, "TS_WCON_CREQ" }, { TS_WRES_CIND, "TS_WRES_CIND" }, { TS_WACK_CRES, "TS_WACK_CRES" }, { TS_DATA_XFER, "TS_DATA_XFER" }, { TS_WIND_ORDREL,"TS_WIND_ORDREL"}, { TS_WREQ_ORDREL,"TS_WREQ_ORDREL"}, { TS_WACK_DREQ6,"TS_WACK_DREQ6" }, { TS_WACK_DREQ7,"TS_WACK_DREQ7" }, { TS_WACK_DREQ9,"TS_WACK_DREQ9" }, { TS_WACK_DREQ10,"TS_WACK_DREQ10"}, { TS_WACK_DREQ11,"TS_WACK_DREQ11"}, { 0, NULL }, }; static const struct xlat provider_flags[] = { { 0, "0" }, { SENDZERO, "SENDZERO" }, { EXPINLINE, "EXPINLINE" }, { XPG4_1, "XPG4_1" }, { 0, NULL }, }; static const struct xlat tli_errors[] = { { TBADADDR, "TBADADDR" }, { TBADOPT, "TBADOPT" }, { TACCES, "TACCES" }, { TBADF, "TBADF" }, { TNOADDR, "TNOADDR" }, { TOUTSTATE, "TOUTSTATE" }, { TBADSEQ, "TBADSEQ" }, { TSYSERR, "TSYSERR" }, { TLOOK, "TLOOK" }, { TBADDATA, "TBADDATA" }, { TBUFOVFLW, "TBUFOVFLW" }, { TFLOW, "TFLOW" }, { TNODATA, "TNODATA" }, { TNODIS, "TNODIS" }, { TNOUDERR, "TNOUDERR" }, { TBADFLAG, "TBADFLAG" }, { TNOREL, "TNOREL" }, { TNOTSUPPORT, "TNOTSUPPORT" }, { TSTATECHNG, "TSTATECHNG" }, { TNOSTRUCTYPE, "TNOSTRUCTYPE" }, { TBADNAME, "TBADNAME" }, { TBADQLEN, "TBADQLEN" }, { TADDRBUSY, "TADDRBUSY" }, { TINDOUT, "TINDOUT" }, { TPROVMISMATCH,"TPROVMISMATCH" }, { TRESQLEN, "TRESQLEN" }, { TRESADDR, "TRESADDR" }, { TQFULL, "TQFULL" }, { TPROTO, "TPROTO" }, { 0, NULL }, }; static int print_transport_message(struct tcb *tcp, int expect, long addr, int len) { union T_primitives m; int c = 0; if (len < sizeof m.type) goto dump; if (umove(tcp, addr, &m.type) < 0) goto dump; #define GET(type, struct) \ do { \ if (len < sizeof m.struct) goto dump; \ if (umove(tcp, addr, &m.struct) < 0) goto dump; \ tprints("{"); \ if (expect != type) { \ ++c; \ tprints(#type); \ } \ } \ while (0) #define COMMA() \ do { if (c++) tprints(", "); } while (0) #define STRUCT(struct, elem, print) \ do { \ COMMA(); \ if (m.struct.elem##_length < 0 || \ m.struct.elem##_offset < sizeof m.struct || \ m.struct.elem##_offset + m.struct.elem##_length > len) \ { \ tprintf(#elem "_length=%ld, " #elem "_offset=%ld",\ m.struct.elem##_length, \ m.struct.elem##_offset); \ } \ else { \ tprints(#elem "="); \ print(tcp, \ addr + m.struct.elem##_offset, \ m.struct.elem##_length); \ } \ } \ while (0) #define ADDR(struct, elem) STRUCT(struct, elem, printstr) switch (m.type) { #ifdef T_CONN_REQ case T_CONN_REQ: /* connect request */ GET(T_CONN_REQ, conn_req); ADDR(conn_req, DEST); ADDR(conn_req, OPT); break; #endif #ifdef T_CONN_RES case T_CONN_RES: /* connect response */ GET(T_CONN_RES, conn_res); #ifdef HAVE_STRUCT_T_CONN_RES_QUEUE_PTR COMMA(); tprintf("QUEUE=%p", m.conn_res.QUEUE_ptr); #elif defined HAVE_STRUCT_T_CONN_RES_ACCEPTOR_ID COMMA(); tprintf("ACCEPTOR=%#lx", m.conn_res.ACCEPTOR_id); #endif ADDR(conn_res, OPT); COMMA(); tprintf("SEQ=%ld", m.conn_res.SEQ_number); break; #endif #ifdef T_DISCON_REQ case T_DISCON_REQ: /* disconnect request */ GET(T_DISCON_REQ, discon_req); COMMA(); tprintf("SEQ=%ld", m.discon_req.SEQ_number); break; #endif #ifdef T_DATA_REQ case T_DATA_REQ: /* data request */ GET(T_DATA_REQ, data_req); COMMA(); tprintf("MORE=%ld", m.data_req.MORE_flag); break; #endif #ifdef T_EXDATA_REQ case T_EXDATA_REQ: /* expedited data req */ GET(T_EXDATA_REQ, exdata_req); COMMA(); tprintf("MORE=%ld", m.exdata_req.MORE_flag); break; #endif #ifdef T_INFO_REQ case T_INFO_REQ: /* information req */ GET(T_INFO_REQ, info_req); break; #endif #ifdef T_BIND_REQ case T_BIND_REQ: /* bind request */ #ifdef O_T_BIND_REQ case O_T_BIND_REQ: /* Ugly xti/tli hack */ #endif GET(T_BIND_REQ, bind_req); ADDR(bind_req, ADDR); COMMA(); tprintf("CONIND=%ld", m.bind_req.CONIND_number); break; #endif #ifdef T_UNBIND_REQ case T_UNBIND_REQ: /* unbind request */ GET(T_UNBIND_REQ, unbind_req); break; #endif #ifdef T_UNITDATA_REQ case T_UNITDATA_REQ: /* unitdata requset */ GET(T_UNITDATA_REQ, unitdata_req); ADDR(unitdata_req, DEST); ADDR(unitdata_req, OPT); break; #endif #ifdef T_OPTMGMT_REQ case T_OPTMGMT_REQ: /* manage opt req */ GET(T_OPTMGMT_REQ, optmgmt_req); COMMA(); tprints("MGMT="); printflags(transport_user_flags, m.optmgmt_req.MGMT_flags, "T_???"); STRUCT(optmgmt_req, OPT, print_optmgmt); break; #endif #ifdef T_ORDREL_REQ case T_ORDREL_REQ: /* orderly rel req */ GET(T_ORDREL_REQ, ordrel_req); break; #endif #ifdef T_CONN_IND case T_CONN_IND: /* connect indication */ GET(T_CONN_IND, conn_ind); ADDR(conn_ind, SRC); ADDR(conn_ind, OPT); tprintf(", SEQ=%ld", m.conn_ind.SEQ_number); break; #endif #ifdef T_CONN_CON case T_CONN_CON: /* connect corfirm */ GET(T_CONN_CON, conn_con); ADDR(conn_con, RES); ADDR(conn_con, OPT); break; #endif #ifdef T_DISCON_IND case T_DISCON_IND: /* discon indication */ GET(T_DISCON_IND, discon_ind); COMMA(); tprintf("DISCON=%ld, SEQ=%ld", m.discon_ind.DISCON_reason, m.discon_ind.SEQ_number); break; #endif #ifdef T_DATA_IND case T_DATA_IND: /* data indication */ GET(T_DATA_IND, data_ind); COMMA(); tprintf("MORE=%ld", m.data_ind.MORE_flag); break; #endif #ifdef T_EXDATA_IND case T_EXDATA_IND: /* expedited data ind */ GET(T_EXDATA_IND, exdata_ind); COMMA(); tprintf("MORE=%ld", m.exdata_ind.MORE_flag); break; #endif #ifdef T_INFO_ACK case T_INFO_ACK: /* info ack */ GET(T_INFO_ACK, info_ack); COMMA(); tprintf("TSDU=%ld, ETSDU=%ld, CDATA=%ld, DDATA=%ld, " "ADDR=%ld, OPT=%ld, TIDU=%ld, SERV=", m.info_ack.TSDU_size, m.info_ack.ETSDU_size, m.info_ack.CDATA_size, m.info_ack.DDATA_size, m.info_ack.ADDR_size, m.info_ack.OPT_size, m.info_ack.TIDU_size); printxval(service_type, m.info_ack.SERV_type, "T_???"); tprints(", CURRENT="); printxval(ts_state, m.info_ack.CURRENT_state, "TS_???"); tprints(", PROVIDER="); printflags(provider_flags, m.info_ack.PROVIDER_flag, "???"); break; #endif #ifdef T_BIND_ACK case T_BIND_ACK: /* bind ack */ GET(T_BIND_ACK, bind_ack); ADDR(bind_ack, ADDR); tprintf(", CONIND=%ld", m.bind_ack.CONIND_number); break; #endif #ifdef T_ERROR_ACK case T_ERROR_ACK: /* error ack */ GET(T_ERROR_ACK, error_ack); COMMA(); tprints("ERROR="); printxval(transport_user_options, m.error_ack.ERROR_prim, "TI_???"); tprints(", TLI="); printxval(tli_errors, m.error_ack.TLI_error, "T???"); tprintf("UNIX=%s", strerror(m.error_ack.UNIX_error)); break; #endif #ifdef T_OK_ACK case T_OK_ACK: /* ok ack */ GET(T_OK_ACK, ok_ack); COMMA(); tprints("CORRECT="); printxval(transport_user_options, m.ok_ack.CORRECT_prim, "TI_???"); break; #endif #ifdef T_UNITDATA_IND case T_UNITDATA_IND: /* unitdata ind */ GET(T_UNITDATA_IND, unitdata_ind); ADDR(unitdata_ind, SRC); ADDR(unitdata_ind, OPT); break; #endif #ifdef T_UDERROR_IND case T_UDERROR_IND: /* unitdata error ind */ GET(T_UDERROR_IND, uderror_ind); ADDR(uderror_ind, DEST); ADDR(uderror_ind, OPT); tprintf(", ERROR=%ld", m.uderror_ind.ERROR_type); break; #endif #ifdef T_OPTMGMT_ACK case T_OPTMGMT_ACK: /* manage opt ack */ GET(T_OPTMGMT_ACK, optmgmt_ack); COMMA(); tprints("MGMT="); printflags(transport_user_flags, m.optmgmt_ack.MGMT_flags, "T_???"); STRUCT(optmgmt_ack, OPT, print_optmgmt); break; #endif #ifdef T_ORDREL_IND case T_ORDREL_IND: /* orderly rel ind */ GET(T_ORDREL_IND, ordrel_ind); break; #endif #ifdef T_ADDR_REQ case T_ADDR_REQ: /* address req */ GET(T_ADDR_REQ, addr_req); break; #endif #ifdef T_ADDR_ACK case T_ADDR_ACK: /* address response */ GET(T_ADDR_ACK, addr_ack); ADDR(addr_ack, LOCADDR); ADDR(addr_ack, REMADDR); break; #endif default: dump: c = -1; printstr(tcp, addr, len); break; } if (c >= 0) tprints("}"); #undef ADDR #undef COMMA #undef STRUCT return 0; } #endif /* TI_BIND */ static int internal_stream_ioctl(struct tcb *tcp, int arg) { struct strioctl si; struct ioctlent *iop; int in_and_out; int timod = 0; #ifdef SI_GETUDATA struct si_udata udata; #endif /* SI_GETUDATA */ if (!arg) return 0; if (umove(tcp, arg, &si) < 0) { if (entering(tcp)) tprints(", {...}"); return 1; } if (entering(tcp)) { iop = ioctl_lookup(si.ic_cmd); if (iop) { tprintf(", {ic_cmd=%s", iop->symbol); while ((iop = ioctl_next_match(iop))) tprintf(" or %s", iop->symbol); } else tprintf(", {ic_cmd=%#x", si.ic_cmd); if (si.ic_timout == INFTIM) tprints(", ic_timout=INFTIM, "); else tprintf(" ic_timout=%d, ", si.ic_timout); } in_and_out = 1; switch (si.ic_cmd) { #ifdef SI_GETUDATA case SI_GETUDATA: in_and_out = 0; break; #endif /* SI_GETUDATA */ } if (in_and_out) { if (entering(tcp)) tprints("/* in */ "); else tprints(", /* out */ "); } if (in_and_out || entering(tcp)) tprintf("ic_len=%d, ic_dp=", si.ic_len); switch (si.ic_cmd) { #ifdef TI_BIND case TI_BIND: /* in T_BIND_REQ, out T_BIND_ACK */ ++timod; if (entering(tcp)) { print_transport_message(tcp, T_BIND_REQ, si.ic_dp, si.ic_len); } else { print_transport_message(tcp, T_BIND_ACK, si.ic_dp, si.ic_len); } break; #endif /* TI_BIND */ #ifdef TI_UNBIND case TI_UNBIND: /* in T_UNBIND_REQ, out T_OK_ACK */ ++timod; if (entering(tcp)) { print_transport_message(tcp, T_UNBIND_REQ, si.ic_dp, si.ic_len); } else { print_transport_message(tcp, T_OK_ACK, si.ic_dp, si.ic_len); } break; #endif /* TI_UNBIND */ #ifdef TI_GETINFO case TI_GETINFO: /* in T_INFO_REQ, out T_INFO_ACK */ ++timod; if (entering(tcp)) { print_transport_message(tcp, T_INFO_REQ, si.ic_dp, si.ic_len); } else { print_transport_message(tcp, T_INFO_ACK, si.ic_dp, si.ic_len); } break; #endif /* TI_GETINFO */ #ifdef TI_OPTMGMT case TI_OPTMGMT: /* in T_OPTMGMT_REQ, out T_OPTMGMT_ACK */ ++timod; if (entering(tcp)) { print_transport_message(tcp, T_OPTMGMT_REQ, si.ic_dp, si.ic_len); } else { print_transport_message(tcp, T_OPTMGMT_ACK, si.ic_dp, si.ic_len); } break; #endif /* TI_OPTMGMT */ #ifdef SI_GETUDATA case SI_GETUDATA: if (entering(tcp)) break; if (umove(tcp, (int) si.ic_dp, &udata) < 0) tprints("{...}"); else { tprintf("{tidusize=%d, addrsize=%d, ", udata.tidusize, udata.addrsize); tprintf("optsize=%d, etsdusize=%d, ", udata.optsize, udata.etsdusize); tprintf("servtype=%d, so_state=%d, ", udata.servtype, udata.so_state); tprintf("so_options=%d", udata.so_options); tprints("}"); } break; #endif /* SI_GETUDATA */ default: printstr(tcp, (long) si.ic_dp, si.ic_len); break; } if (exiting(tcp)) { tprints("}"); if (timod && tcp->u_rval && !syserror(tcp)) { tcp->auxstr = xlookup(tli_errors, tcp->u_rval); return RVAL_STR + 1; } } return 1; } int stream_ioctl(struct tcb *tcp, int code, int arg) { #ifdef I_LIST int i; #endif int val; #ifdef I_FLUSHBAND struct bandinfo bi; #endif struct strpeek sp; struct strfdinsert sfi; struct strrecvfd srf; #ifdef I_LIST struct str_list sl; #endif /* I_STR is a special case because the data is read & written. */ if (code == I_STR) return internal_stream_ioctl(tcp, arg); if (entering(tcp)) return 0; switch (code) { case I_PUSH: case I_LOOK: case I_FIND: /* arg is a string */ tprints(", "); printpath(tcp, arg); return 1; case I_POP: /* doesn't take an argument */ return 1; case I_FLUSH: /* argument is an option */ tprints(", "); printxval(stream_flush_options, arg, "FLUSH???"); return 1; #ifdef I_FLUSHBAND case I_FLUSHBAND: /* argument is a pointer to a bandinfo struct */ if (umove(tcp, arg, &bi) < 0) tprints(", {...}"); else { tprintf(", {bi_pri=%d, bi_flag=", bi.bi_pri); printflags(stream_flush_options, bi.bi_flag, "FLUSH???"); tprints("}"); } return 1; #endif /* I_FLUSHBAND */ case I_SETSIG: /* argument is a set of flags */ tprints(", "); printflags(stream_setsig_flags, arg, "S_???"); return 1; case I_GETSIG: /* argument is a pointer to a set of flags */ if (syserror(tcp)) return 0; tprints(", ["); if (umove(tcp, arg, &val) < 0) tprints("?"); else printflags(stream_setsig_flags, val, "S_???"); tprints("]"); return 1; case I_PEEK: /* argument is a pointer to a strpeek structure */ if (syserror(tcp) || !arg) return 0; if (umove(tcp, arg, &sp) < 0) { tprints(", {...}"); return 1; } tprints(", {ctlbuf="); printstrbuf(tcp, &sp.ctlbuf, 1); tprints(", databuf="); printstrbuf(tcp, &sp.databuf, 1); tprints(", flags="); printflags(msgflags, sp.flags, "RS_???"); tprints("}"); return 1; case I_SRDOPT: /* argument is an option with flags */ tprints(", "); printxval(stream_read_options, arg & RMODEMASK, "R???"); addflags(stream_read_flags, arg & ~RMODEMASK); return 1; case I_GRDOPT: /* argument is an pointer to an option with flags */ if (syserror(tcp)) return 0; tprints(", ["); if (umove(tcp, arg, &val) < 0) tprints("?"); else { printxval(stream_read_options, arg & RMODEMASK, "R???"); addflags(stream_read_flags, arg & ~RMODEMASK); } tprints("]"); return 1; case I_NREAD: #ifdef I_GETBAND case I_GETBAND: #endif #ifdef I_SETCLTIME case I_SETCLTIME: #endif #ifdef I_GETCLTIME case I_GETCLTIME: #endif /* argument is a pointer to a decimal integer */ if (syserror(tcp)) return 0; tprints(", "); printnum(tcp, arg, "%d"); return 1; case I_FDINSERT: /* argument is a pointer to a strfdinsert structure */ if (syserror(tcp) || !arg) return 0; if (umove(tcp, arg, &sfi) < 0) { tprints(", {...}"); return 1; } tprints(", {ctlbuf="); printstrbuf(tcp, &sfi.ctlbuf, 1); tprints(", databuf="); printstrbuf(tcp, &sfi.databuf, 1); tprints(", flags="); printflags(msgflags, sfi.flags, "RS_???"); tprintf(", filedes=%d, offset=%d}", sfi.fildes, sfi.offset); return 1; #ifdef I_SWROPT case I_SWROPT: /* argument is a set of flags */ tprints(", "); printflags(stream_write_flags, arg, "SND???"); return 1; #endif /* I_SWROPT */ #ifdef I_GWROPT case I_GWROPT: /* argument is an pointer to an option with flags */ if (syserror(tcp)) return 0; tprints(", ["); if (umove(tcp, arg, &val) < 0) tprints("?"); else printflags(stream_write_flags, arg, "SND???"); tprints("]"); return 1; #endif /* I_GWROPT */ case I_SENDFD: #ifdef I_CKBAND case I_CKBAND: #endif #ifdef I_CANPUT case I_CANPUT: #endif case I_LINK: case I_UNLINK: case I_PLINK: case I_PUNLINK: /* argument is a decimal integer */ tprintf(", %d", arg); return 1; case I_RECVFD: /* argument is a pointer to a strrecvfd structure */ if (syserror(tcp) || !arg) return 0; if (umove(tcp, arg, &srf) < 0) { tprints(", {...}"); return 1; } tprintf(", {fd=%d, uid=%lu, gid=%lu}", srf.fd, (unsigned long) srf.uid, (unsigned long) srf.gid); return 1; #ifdef I_LIST case I_LIST: if (syserror(tcp)) return 0; if (arg == 0) { tprints(", NULL"); return 1; } if (umove(tcp, arg, &sl) < 0) { tprints(", {...}"); return 1; } tprintf(", {sl_nmods=%d, sl_modlist=[", sl.sl_nmods); for (i = 0; i < tcp->u_rval; i++) { if (i) tprints(", "); printpath(tcp, (int) sl.sl_modlist[i].l_name); } tprints("]}"); return 1; #endif /* I_LIST */ #ifdef I_ATMARK case I_ATMARK: tprints(", "); printxval(stream_atmark_options, arg, "???MARK"); return 1; #endif /* I_ATMARK */ default: return 0; } } #endif /* !LINUX && !FREEBSD */ #endif /* HAVE_SYS_STREAM_H || LINUX || FREEBSD */