stream.c revision b9fe011cdfb0a3014e68a6e82007b6c2703a340b
1/* 2 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com> 3 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $Id$ 29 */ 30 31#include "defs.h" 32#include <sys/syscall.h> 33 34#ifdef HAVE_POLL_H 35#include <poll.h> 36#endif 37#ifdef HAVE_SYS_POLL_H 38#include <sys/poll.h> 39#endif 40#ifdef HAVE_STROPTS_H 41#include <stropts.h> 42#endif 43#ifdef HAVE_SYS_CONF_H 44#include <sys/conf.h> 45#endif 46#ifdef HAVE_SYS_STREAM_H 47#include <sys/stream.h> 48#endif 49#ifdef HAVE_SYS_TIHDR_H 50#include <sys/tihdr.h> 51#endif 52 53#if defined(HAVE_SYS_STREAM_H) || defined(LINUX) || defined(FREEBSD) 54 55#ifndef HAVE_STROPTS_H 56#define RS_HIPRI 1 57struct strbuf { 58 int maxlen; /* no. of bytes in buffer */ 59 int len; /* no. of bytes returned */ 60 char *buf; /* pointer to data */ 61}; 62#define MORECTL 1 63#define MOREDATA 2 64#endif /* !HAVE_STROPTS_H */ 65 66#ifdef HAVE_SYS_TIUSER_H 67#include <sys/tiuser.h> 68#include <sys/sockmod.h> 69#include <sys/timod.h> 70#endif /* HAVE_SYS_TIUSER_H */ 71 72#ifndef FREEBSD 73static const struct xlat msgflags[] = { 74 { RS_HIPRI, "RS_HIPRI" }, 75 { 0, NULL }, 76}; 77 78 79static void 80printstrbuf(tcp, sbp, getting) 81struct tcb *tcp; 82struct strbuf *sbp; 83int getting; 84{ 85 if (sbp->maxlen == -1 && getting) 86 tprintf("{maxlen=-1}"); 87 else { 88 tprintf("{"); 89 if (getting) 90 tprintf("maxlen=%d, ", sbp->maxlen); 91 tprintf("len=%d, buf=", sbp->len); 92 printstr(tcp, (unsigned long) sbp->buf, sbp->len); 93 tprintf("}"); 94 } 95} 96 97static void 98printstrbufarg(tcp, arg, getting) 99struct tcb *tcp; 100int arg; 101int getting; 102{ 103 struct strbuf buf; 104 105 if (arg == 0) 106 tprintf("NULL"); 107 else if (umove(tcp, arg, &buf) < 0) 108 tprintf("{...}"); 109 else 110 printstrbuf(tcp, &buf, getting); 111 tprintf(", "); 112} 113 114int 115sys_putmsg(tcp) 116struct tcb *tcp; 117{ 118 int i; 119 120 if (entering(tcp)) { 121 /* fd */ 122 tprintf("%ld, ", tcp->u_arg[0]); 123 /* control and data */ 124 for (i = 1; i < 3; i++) 125 printstrbufarg(tcp, tcp->u_arg[i], 0); 126 /* flags */ 127 printflags(msgflags, tcp->u_arg[3], "RS_???"); 128 } 129 return 0; 130} 131 132#if defined(SPARC) || defined(SPARC64) || defined(SUNOS4) || defined(SVR4) 133int 134sys_getmsg(tcp) 135struct tcb *tcp; 136{ 137 int i, flags; 138 139 if (entering(tcp)) { 140 /* fd */ 141 tprintf("%lu, ", tcp->u_arg[0]); 142 } else { 143 if (syserror(tcp)) { 144 tprintf("%#lx, %#lx, %#lx", 145 tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3]); 146 return 0; 147 } 148 /* control and data */ 149 for (i = 1; i < 3; i++) 150 printstrbufarg(tcp, tcp->u_arg[i], 1); 151 /* pointer to flags */ 152 if (tcp->u_arg[3] == 0) 153 tprintf("NULL"); 154 else if (umove(tcp, tcp->u_arg[3], &flags) < 0) 155 tprintf("[?]"); 156 else { 157 tprintf("["); 158 printflags(msgflags, flags, "RS_???"); 159 tprintf("]"); 160 } 161 /* decode return value */ 162 switch (tcp->u_rval) { 163 case MORECTL: 164 tcp->auxstr = "MORECTL"; 165 break; 166 case MORECTL|MOREDATA: 167 tcp->auxstr = "MORECTL|MOREDATA"; 168 break; 169 case MOREDATA: 170 tcp->auxstr = "MORECTL"; 171 break; 172 default: 173 tcp->auxstr = NULL; 174 break; 175 } 176 } 177 return RVAL_HEX | RVAL_STR; 178} 179#endif /* SPARC || SPARC64 || SUNOS4 || SVR4 */ 180 181#if defined SYS_putpmsg || defined SYS_getpmsg 182static const struct xlat pmsgflags[] = { 183#ifdef MSG_HIPRI 184 { MSG_HIPRI, "MSG_HIPRI" }, 185#endif 186#ifdef MSG_AND 187 { MSG_ANY, "MSG_ANY" }, 188#endif 189#ifdef MSG_BAND 190 { MSG_BAND, "MSG_BAND" }, 191#endif 192 { 0, NULL }, 193}; 194#endif 195 196#ifdef SYS_putpmsg 197int 198sys_putpmsg(tcp) 199struct tcb *tcp; 200{ 201 int i; 202 203 if (entering(tcp)) { 204 /* fd */ 205 tprintf("%ld, ", tcp->u_arg[0]); 206 /* control and data */ 207 for (i = 1; i < 3; i++) 208 printstrbufarg(tcp, tcp->u_arg[i], 0); 209 /* band */ 210 tprintf("%ld, ", tcp->u_arg[3]); 211 /* flags */ 212 printflags(pmsgflags, tcp->u_arg[4], "MSG_???"); 213 } 214 return 0; 215} 216#endif /* SYS_putpmsg */ 217 218#ifdef SYS_getpmsg 219int 220sys_getpmsg(tcp) 221struct tcb *tcp; 222{ 223 int i, flags; 224 225 if (entering(tcp)) { 226 /* fd */ 227 tprintf("%lu, ", tcp->u_arg[0]); 228 } else { 229 if (syserror(tcp)) { 230 tprintf("%#lx, %#lx, %#lx, %#lx", tcp->u_arg[1], 231 tcp->u_arg[2], tcp->u_arg[3], tcp->u_arg[4]); 232 return 0; 233 } 234 /* control and data */ 235 for (i = 1; i < 3; i++) 236 printstrbufarg(tcp, tcp->u_arg[i], 1); 237 /* pointer to band */ 238 printnum(tcp, tcp->u_arg[3], "%d"); 239 tprintf(", "); 240 /* pointer to flags */ 241 if (tcp->u_arg[4] == 0) 242 tprintf("NULL"); 243 else if (umove(tcp, tcp->u_arg[4], &flags) < 0) 244 tprintf("[?]"); 245 else { 246 tprintf("["); 247 printflags(pmsgflags, flags, "MSG_???"); 248 tprintf("]"); 249 } 250 /* decode return value */ 251 switch (tcp->u_rval) { 252 case MORECTL: 253 tcp->auxstr = "MORECTL"; 254 break; 255 case MORECTL|MOREDATA: 256 tcp->auxstr = "MORECTL|MOREDATA"; 257 break; 258 case MOREDATA: 259 tcp->auxstr = "MORECTL"; 260 break; 261 default: 262 tcp->auxstr = NULL; 263 break; 264 } 265 } 266 return RVAL_HEX | RVAL_STR; 267} 268#endif /* SYS_getpmsg */ 269 270#endif /* !FREEBSD */ 271 272 273#ifdef HAVE_SYS_POLL_H 274 275static const struct xlat pollflags[] = { 276#ifdef POLLIN 277 { POLLIN, "POLLIN" }, 278 { POLLPRI, "POLLPRI" }, 279 { POLLOUT, "POLLOUT" }, 280#ifdef POLLRDNORM 281 { POLLRDNORM, "POLLRDNORM" }, 282#endif 283#ifdef POLLWRNORM 284 { POLLWRNORM, "POLLWRNORM" }, 285#endif 286#ifdef POLLRDBAND 287 { POLLRDBAND, "POLLRDBAND" }, 288#endif 289#ifdef POLLWRBAND 290 { POLLWRBAND, "POLLWRBAND" }, 291#endif 292 { POLLERR, "POLLERR" }, 293 { POLLHUP, "POLLHUP" }, 294 { POLLNVAL, "POLLNVAL" }, 295#endif 296 { 0, NULL }, 297}; 298 299static int 300decode_poll(struct tcb *tcp) 301{ 302 struct pollfd fds; 303 unsigned nfds; 304 unsigned long size, start, cur, end, abbrev_end; 305 int failed = 0; 306 307 if (entering(tcp)) 308 return 0; 309 310 nfds = tcp->u_arg[1]; 311 size = sizeof(fds) * nfds; 312 start = tcp->u_arg[0]; 313 end = start + size; 314 if (nfds == 0 || size / sizeof(fds) != nfds || end < start) { 315 tprintf("%#lx, %d, ", 316 tcp->u_arg[0], nfds); 317 return 0; 318 } 319 if (abbrev(tcp)) { 320 abbrev_end = start + max_strlen * sizeof(fds); 321 if (abbrev_end < start) 322 abbrev_end = end; 323 } else { 324 abbrev_end = end; 325 } 326 tprintf("["); 327 for (cur = start; cur < end; cur += sizeof(fds)) { 328 if (cur > start) 329 tprintf(", "); 330 if (cur >= abbrev_end) { 331 tprintf("..."); 332 break; 333 } 334 if (umoven(tcp, cur, sizeof fds, (char *) &fds) < 0) { 335 tprintf("?"); 336 failed = 1; 337 break; 338 } 339 if (fds.fd < 0) { 340 tprintf("{fd=%d}", fds.fd); 341 continue; 342 } 343 tprintf("{fd=%d, events=", fds.fd); 344 printflags(pollflags, fds.events, "POLL???"); 345 if (!syserror(tcp) && fds.revents) { 346 tprintf(", revents="); 347 printflags(pollflags, fds.revents, "POLL???"); 348 } 349 tprintf("}"); 350 } 351 tprintf("]"); 352 if (failed) 353 tprintf(" %#lx", start); 354 tprintf(", %d, ", nfds); 355 return 0; 356} 357 358int 359sys_poll(struct tcb *tcp) 360{ 361 int rc = decode_poll(tcp); 362 if (exiting(tcp)) { 363#ifdef INFTIM 364 if (tcp->u_arg[2] == INFTIM) 365 tprintf("INFTIM"); 366 else 367#endif 368 tprintf("%ld", tcp->u_arg[2]); 369 } 370 return rc; 371} 372 373#ifdef LINUX 374int 375sys_ppoll(struct tcb *tcp) 376{ 377 int rc = decode_poll(tcp); 378 if (exiting(tcp)) { 379 struct timespec ts; 380 if (umove(tcp, tcp->u_arg[2], &ts) == 0) 381 tprintf("{%lu, %lu}, ", ts.tv_sec, ts.tv_nsec); 382 else 383 tprintf("{...}, "); 384 print_sigset(tcp, tcp->u_arg[3], 0); 385 tprintf(", %lu", tcp->u_arg[4]); 386 } 387 return rc; 388} 389#endif 390 391#else /* !HAVE_SYS_POLL_H */ 392int 393sys_poll(tcp) 394struct tcb *tcp; 395{ 396 return 0; 397} 398#endif 399 400#if !defined(LINUX) && !defined(FREEBSD) 401 402static const struct xlat stream_flush_options[] = { 403 { FLUSHR, "FLUSHR" }, 404 { FLUSHW, "FLUSHW" }, 405 { FLUSHRW, "FLUSHRW" }, 406#ifdef FLUSHBAND 407 { FLUSHBAND, "FLUSHBAND" }, 408#endif 409 { 0, NULL }, 410}; 411 412static const struct xlat stream_setsig_flags[] = { 413 { S_INPUT, "S_INPUT" }, 414 { S_HIPRI, "S_HIPRI" }, 415 { S_OUTPUT, "S_OUTPUT" }, 416 { S_MSG, "S_MSG" }, 417#ifdef S_ERROR 418 { S_ERROR, "S_ERROR" }, 419#endif 420#ifdef S_HANGUP 421 { S_HANGUP, "S_HANGUP" }, 422#endif 423#ifdef S_RDNORM 424 { S_RDNORM, "S_RDNORM" }, 425#endif 426#ifdef S_WRNORM 427 { S_WRNORM, "S_WRNORM" }, 428#endif 429#ifdef S_RDBAND 430 { S_RDBAND, "S_RDBAND" }, 431#endif 432#ifdef S_WRBAND 433 { S_WRBAND, "S_WRBAND" }, 434#endif 435#ifdef S_BANDURG 436 { S_BANDURG, "S_BANDURG" }, 437#endif 438 { 0, NULL }, 439}; 440 441static const struct xlat stream_read_options[] = { 442 { RNORM, "RNORM" }, 443 { RMSGD, "RMSGD" }, 444 { RMSGN, "RMSGN" }, 445 { 0, NULL }, 446}; 447 448static const struct xlat stream_read_flags[] = { 449#ifdef RPROTDAT 450 { RPROTDAT, "RPROTDAT" }, 451#endif 452#ifdef RPROTDIS 453 { RPROTDIS, "RPROTDIS" }, 454#endif 455#ifdef RPROTNORM 456 { RPROTNORM, "RPROTNORM" }, 457#endif 458 { 0, NULL }, 459}; 460 461#ifndef RMODEMASK 462#define RMODEMASK (~0) 463#endif 464 465#ifdef I_SWROPT 466static const struct xlat stream_write_flags[] = { 467 { SNDZERO, "SNDZERO" }, 468 { SNDPIPE, "SNDPIPE" }, 469 { 0, NULL }, 470}; 471#endif /* I_SWROPT */ 472 473#ifdef I_ATMARK 474static const struct xlat stream_atmark_options[] = { 475 { ANYMARK, "ANYMARK" }, 476 { LASTMARK, "LASTMARK" }, 477 { 0, NULL }, 478}; 479#endif /* I_ATMARK */ 480 481#ifdef TI_BIND 482static const struct xlat transport_user_options[] = { 483 { T_CONN_REQ, "T_CONN_REQ" }, 484 { T_CONN_RES, "T_CONN_RES" }, 485 { T_DISCON_REQ, "T_DISCON_REQ" }, 486 { T_DATA_REQ, "T_DATA_REQ" }, 487 { T_EXDATA_REQ, "T_EXDATA_REQ" }, 488 { T_INFO_REQ, "T_INFO_REQ" }, 489 { T_BIND_REQ, "T_BIND_REQ" }, 490 { T_UNBIND_REQ, "T_UNBIND_REQ" }, 491 { T_UNITDATA_REQ,"T_UNITDATA_REQ"}, 492 { T_OPTMGMT_REQ,"T_OPTMGMT_REQ" }, 493 { T_ORDREL_REQ, "T_ORDREL_REQ" }, 494 { 0, NULL }, 495}; 496 497static const struct xlat transport_user_flags [] = { 498 { 0, "0" }, 499 { T_MORE, "T_MORE" }, 500 { T_EXPEDITED, "T_EXPEDITED" }, 501 { T_NEGOTIATE, "T_NEGOTIATE" }, 502 { T_CHECK, "T_CHECK" }, 503 { T_DEFAULT, "T_DEFAULT" }, 504 { T_SUCCESS, "T_SUCCESS" }, 505 { T_FAILURE, "T_FAILURE" }, 506 { T_CURRENT, "T_CURRENT" }, 507 { T_PARTSUCCESS,"T_PARTSUCCESS" }, 508 { T_READONLY, "T_READONLY" }, 509 { T_NOTSUPPORT, "T_NOTSUPPORT" }, 510 { 0, NULL }, 511}; 512 513 514#ifdef HAVE_STRUCT_T_OPTHDR 515 516static const struct xlat xti_level [] = { 517 { XTI_GENERIC, "XTI_GENERIC" }, 518 { 0, NULL }, 519}; 520 521static const struct xlat xti_generic [] = { 522 { XTI_DEBUG, "XTI_DEBUG" }, 523 { XTI_LINGER, "XTI_LINGER" }, 524 { XTI_RCVBUF, "XTI_RCVBUF" }, 525 { XTI_RCVLOWAT, "XTI_RCVLOWAT" }, 526 { XTI_SNDBUF, "XTI_SNDBUF" }, 527 { XTI_SNDLOWAT, "XTI_SNDLOWAT" }, 528 { 0, NULL }, 529}; 530 531 532 533void 534print_xti_optmgmt (tcp, addr, len) 535struct tcb *tcp; 536long addr; 537int len; 538{ 539 int c = 0; 540 struct t_opthdr hdr; 541 542 while (len >= (int) sizeof hdr) { 543 if (umove(tcp, addr, &hdr) < 0) break; 544 if (c++) { 545 tprintf (", "); 546 } 547 else if (len > hdr.len + sizeof hdr) { 548 tprintf ("["); 549 } 550 tprintf ("{level="); 551 printxval (xti_level, hdr.level, "???"); 552 tprintf (", name="); 553 switch (hdr.level) { 554 case XTI_GENERIC: 555 printxval (xti_generic, hdr.name, "XTI_???"); 556 break; 557 default: 558 tprintf ("%ld", hdr.name); 559 break; 560 } 561 tprintf (", status="); 562 printxval (transport_user_flags, hdr.status, "T_???"); 563 addr += sizeof hdr; 564 len -= sizeof hdr; 565 if ((hdr.len -= sizeof hdr) > 0) { 566 if (hdr.len > len) break; 567 tprintf (", val="); 568 if (len == sizeof (int)) 569 printnum (tcp, addr, "%d"); 570 else 571 printstr (tcp, addr, hdr.len); 572 addr += hdr.len; 573 len -= hdr.len; 574 } 575 tprintf ("}"); 576 } 577 if (len > 0) { 578 if (c++) tprintf (", "); 579 printstr (tcp, addr, len); 580 } 581 if (c > 1) tprintf ("]"); 582} 583 584#endif 585 586 587static void 588print_optmgmt (tcp, addr, len) 589struct tcb *tcp; 590long addr; 591int len; 592{ 593 /* We don't know how to tell if TLI (socket) or XTI 594 optmgmt is being used yet, assume TLI. */ 595#if defined (HAVE_STRUCT_OPTHDR) 596 print_sock_optmgmt (tcp, addr, len); 597#elif defined (HAVE_STRUCT_T_OPTHDR) 598 print_xti_optmgmt (tcp, addr, len); 599#else 600 printstr (tcp, addr, len); 601#endif 602} 603 604 605 606 607static const struct xlat service_type [] = { 608 { T_COTS, "T_COTS" }, 609 { T_COTS_ORD, "T_COTS_ORD" }, 610 { T_CLTS, "T_CLTS" }, 611 { 0, NULL }, 612}; 613 614static const struct xlat ts_state [] = { 615 { TS_UNBND, "TS_UNBND" }, 616 { TS_WACK_BREQ, "TS_WACK_BREQ" }, 617 { TS_WACK_UREQ, "TS_WACK_UREQ" }, 618 { TS_IDLE, "TS_IDLE" }, 619 { TS_WACK_OPTREQ,"TS_WACK_OPTREQ"}, 620 { TS_WACK_CREQ, "TS_WACK_CREQ" }, 621 { TS_WCON_CREQ, "TS_WCON_CREQ" }, 622 { TS_WRES_CIND, "TS_WRES_CIND" }, 623 { TS_WACK_CRES, "TS_WACK_CRES" }, 624 { TS_DATA_XFER, "TS_DATA_XFER" }, 625 { TS_WIND_ORDREL,"TS_WIND_ORDREL"}, 626 { TS_WREQ_ORDREL,"TS_WREQ_ORDREL"}, 627 { TS_WACK_DREQ6,"TS_WACK_DREQ6" }, 628 { TS_WACK_DREQ7,"TS_WACK_DREQ7" }, 629 { TS_WACK_DREQ9,"TS_WACK_DREQ9" }, 630 { TS_WACK_DREQ10,"TS_WACK_DREQ10"}, 631 { TS_WACK_DREQ11,"TS_WACK_DREQ11"}, 632 { 0, NULL }, 633}; 634 635static const struct xlat provider_flags [] = { 636 { 0, "0" }, 637 { SENDZERO, "SENDZERO" }, 638 { EXPINLINE, "EXPINLINE" }, 639 { XPG4_1, "XPG4_1" }, 640 { 0, NULL }, 641}; 642 643 644static const struct xlat tli_errors [] = { 645 { TBADADDR, "TBADADDR" }, 646 { TBADOPT, "TBADOPT" }, 647 { TACCES, "TACCES" }, 648 { TBADF, "TBADF" }, 649 { TNOADDR, "TNOADDR" }, 650 { TOUTSTATE, "TOUTSTATE" }, 651 { TBADSEQ, "TBADSEQ" }, 652 { TSYSERR, "TSYSERR" }, 653 { TLOOK, "TLOOK" }, 654 { TBADDATA, "TBADDATA" }, 655 { TBUFOVFLW, "TBUFOVFLW" }, 656 { TFLOW, "TFLOW" }, 657 { TNODATA, "TNODATA" }, 658 { TNODIS, "TNODIS" }, 659 { TNOUDERR, "TNOUDERR" }, 660 { TBADFLAG, "TBADFLAG" }, 661 { TNOREL, "TNOREL" }, 662 { TNOTSUPPORT, "TNOTSUPPORT" }, 663 { TSTATECHNG, "TSTATECHNG" }, 664 { TNOSTRUCTYPE, "TNOSTRUCTYPE" }, 665 { TBADNAME, "TBADNAME" }, 666 { TBADQLEN, "TBADQLEN" }, 667 { TADDRBUSY, "TADDRBUSY" }, 668 { TINDOUT, "TINDOUT" }, 669 { TPROVMISMATCH,"TPROVMISMATCH" }, 670 { TRESQLEN, "TRESQLEN" }, 671 { TRESADDR, "TRESADDR" }, 672 { TQFULL, "TQFULL" }, 673 { TPROTO, "TPROTO" }, 674 { 0, NULL }, 675}; 676 677 678static int 679print_transport_message (tcp, expect, addr, len) 680struct tcb *tcp; 681int expect; 682long addr; 683int len; 684{ 685 union T_primitives m; 686 int c = 0; 687 688 if (len < sizeof m.type) goto dump; 689 690 if (umove (tcp, addr, &m.type) < 0) goto dump; 691 692#define GET(type, struct) \ 693 do { \ 694 if (len < sizeof m.struct) goto dump; \ 695 if (umove (tcp, addr, &m.struct) < 0) goto dump;\ 696 tprintf ("{"); \ 697 if (expect != type) { \ 698 ++c; \ 699 tprintf (#type); \ 700 } \ 701 } \ 702 while (0) 703 704#define COMMA() \ 705 do { if (c++) tprintf (", "); } while (0) 706 707 708#define STRUCT(struct, elem, print) \ 709 do { \ 710 COMMA (); \ 711 if (m.struct.elem##_length < 0 || \ 712 m.struct.elem##_offset < sizeof m.struct || \ 713 m.struct.elem##_offset + m.struct.elem##_length > len) \ 714 { \ 715 tprintf (#elem "_length=%ld, " #elem "_offset=%ld",\ 716 m.struct.elem##_length, \ 717 m.struct.elem##_offset); \ 718 } \ 719 else { \ 720 tprintf (#elem "="); \ 721 print (tcp, \ 722 addr + m.struct.elem##_offset, \ 723 m.struct.elem##_length); \ 724 } \ 725 } \ 726 while (0) 727 728#define ADDR(struct, elem) STRUCT (struct, elem, printstr) 729 730 switch (m.type) { 731#ifdef T_CONN_REQ 732 case T_CONN_REQ: /* connect request */ 733 GET (T_CONN_REQ, conn_req); 734 ADDR (conn_req, DEST); 735 ADDR (conn_req, OPT); 736 break; 737#endif 738#ifdef T_CONN_RES 739 case T_CONN_RES: /* connect response */ 740 GET (T_CONN_RES, conn_res); 741#ifdef HAVE_STRUCT_T_CONN_RES_QUEUE_PTR 742 COMMA (); 743 tprintf ("QUEUE=%p", m.conn_res.QUEUE_ptr); 744#elif defined HAVE_STRUCT_T_CONN_RES_ACCEPTOR_ID 745 COMMA (); 746 tprintf ("ACCEPTOR=%#lx", m.conn_res.ACCEPTOR_id); 747#endif 748 ADDR (conn_res, OPT); 749 COMMA (); 750 tprintf ("SEQ=%ld", m.conn_res.SEQ_number); 751 break; 752#endif 753#ifdef T_DISCON_REQ 754 case T_DISCON_REQ: /* disconnect request */ 755 GET (T_DISCON_REQ, discon_req); 756 COMMA (); 757 tprintf ("SEQ=%ld", m.discon_req.SEQ_number); 758 break; 759#endif 760#ifdef T_DATA_REQ 761 case T_DATA_REQ: /* data request */ 762 GET (T_DATA_REQ, data_req); 763 COMMA (); 764 tprintf ("MORE=%ld", m.data_req.MORE_flag); 765 break; 766#endif 767#ifdef T_EXDATA_REQ 768 case T_EXDATA_REQ: /* expedited data req */ 769 GET (T_EXDATA_REQ, exdata_req); 770 COMMA (); 771 tprintf ("MORE=%ld", m.exdata_req.MORE_flag); 772 break; 773#endif 774#ifdef T_INFO_REQ 775 case T_INFO_REQ: /* information req */ 776 GET (T_INFO_REQ, info_req); 777 break; 778#endif 779#ifdef T_BIND_REQ 780 case T_BIND_REQ: /* bind request */ 781#ifdef O_T_BIND_REQ 782 case O_T_BIND_REQ: /* Ugly xti/tli hack */ 783#endif 784 GET (T_BIND_REQ, bind_req); 785 ADDR (bind_req, ADDR); 786 COMMA (); 787 tprintf ("CONIND=%ld", m.bind_req.CONIND_number); 788 break; 789#endif 790#ifdef T_UNBIND_REQ 791 case T_UNBIND_REQ: /* unbind request */ 792 GET (T_UNBIND_REQ, unbind_req); 793 break; 794#endif 795#ifdef T_UNITDATA_REQ 796 case T_UNITDATA_REQ: /* unitdata requset */ 797 GET (T_UNITDATA_REQ, unitdata_req); 798 ADDR (unitdata_req, DEST); 799 ADDR (unitdata_req, OPT); 800 break; 801#endif 802#ifdef T_OPTMGMT_REQ 803 case T_OPTMGMT_REQ: /* manage opt req */ 804 GET (T_OPTMGMT_REQ, optmgmt_req); 805 COMMA (); 806 tprintf ("MGMT="); 807 printflags (transport_user_flags, m.optmgmt_req.MGMT_flags, 808 "T_???"); 809 STRUCT (optmgmt_req, OPT, print_optmgmt); 810 break; 811#endif 812#ifdef T_ORDREL_REQ 813 case T_ORDREL_REQ: /* orderly rel req */ 814 GET (T_ORDREL_REQ, ordrel_req); 815 break; 816#endif 817#ifdef T_CONN_IND 818 case T_CONN_IND: /* connect indication */ 819 GET (T_CONN_IND, conn_ind); 820 ADDR (conn_ind, SRC); 821 ADDR (conn_ind, OPT); 822 tprintf (", SEQ=%ld", m.conn_ind.SEQ_number); 823 break; 824#endif 825#ifdef T_CONN_CON 826 case T_CONN_CON: /* connect corfirm */ 827 GET (T_CONN_CON, conn_con); 828 ADDR (conn_con, RES); 829 ADDR (conn_con, OPT); 830 break; 831#endif 832#ifdef T_DISCON_IND 833 case T_DISCON_IND: /* discon indication */ 834 GET (T_DISCON_IND, discon_ind); 835 COMMA (); 836 tprintf ("DISCON=%ld, SEQ=%ld", 837 m.discon_ind.DISCON_reason, m.discon_ind.SEQ_number); 838 break; 839#endif 840#ifdef T_DATA_IND 841 case T_DATA_IND: /* data indication */ 842 GET (T_DATA_IND, data_ind); 843 COMMA (); 844 tprintf ("MORE=%ld", m.data_ind.MORE_flag); 845 break; 846#endif 847#ifdef T_EXDATA_IND 848 case T_EXDATA_IND: /* expedited data ind */ 849 GET (T_EXDATA_IND, exdata_ind); 850 COMMA (); 851 tprintf ("MORE=%ld", m.exdata_ind.MORE_flag); 852 break; 853#endif 854#ifdef T_INFO_ACK 855 case T_INFO_ACK: /* info ack */ 856 GET (T_INFO_ACK, info_ack); 857 COMMA (); 858 tprintf ("TSDU=%ld, ETSDU=%ld, CDATA=%ld, DDATA=%ld, " 859 "ADDR=%ld, OPT=%ld, TIDU=%ld, SERV=", 860 m.info_ack.TSDU_size, m.info_ack.ETSDU_size, 861 m.info_ack.CDATA_size, m.info_ack.DDATA_size, 862 m.info_ack.ADDR_size, m.info_ack.OPT_size, 863 m.info_ack.TIDU_size); 864 printxval (service_type, m.info_ack.SERV_type, "T_???"); 865 tprintf (", CURRENT="); 866 printxval (ts_state, m.info_ack.CURRENT_state, "TS_???"); 867 tprintf (", PROVIDER="); 868 printflags (provider_flags, m.info_ack.PROVIDER_flag, "???"); 869 break; 870#endif 871#ifdef T_BIND_ACK 872 case T_BIND_ACK: /* bind ack */ 873 GET (T_BIND_ACK, bind_ack); 874 ADDR (bind_ack, ADDR); 875 tprintf (", CONIND=%ld", m.bind_ack.CONIND_number); 876 break; 877#endif 878#ifdef T_ERROR_ACK 879 case T_ERROR_ACK: /* error ack */ 880 GET (T_ERROR_ACK, error_ack); 881 COMMA (); 882 tprintf ("ERROR="); 883 printxval (transport_user_options, 884 m.error_ack.ERROR_prim, "TI_???"); 885 tprintf (", TLI="); 886 printxval (tli_errors, m.error_ack.TLI_error, "T???"); 887 tprintf ("UNIX=%s", strerror (m.error_ack.UNIX_error)); 888 break; 889#endif 890#ifdef T_OK_ACK 891 case T_OK_ACK: /* ok ack */ 892 GET (T_OK_ACK, ok_ack); 893 COMMA (); 894 tprintf ("CORRECT="); 895 printxval (transport_user_options, 896 m.ok_ack.CORRECT_prim, "TI_???"); 897 break; 898#endif 899#ifdef T_UNITDATA_IND 900 case T_UNITDATA_IND: /* unitdata ind */ 901 GET (T_UNITDATA_IND, unitdata_ind); 902 ADDR (unitdata_ind, SRC); 903 ADDR (unitdata_ind, OPT); 904 break; 905#endif 906#ifdef T_UDERROR_IND 907 case T_UDERROR_IND: /* unitdata error ind */ 908 GET (T_UDERROR_IND, uderror_ind); 909 ADDR (uderror_ind, DEST); 910 ADDR (uderror_ind, OPT); 911 tprintf (", ERROR=%ld", m.uderror_ind.ERROR_type); 912 break; 913#endif 914#ifdef T_OPTMGMT_ACK 915 case T_OPTMGMT_ACK: /* manage opt ack */ 916 GET (T_OPTMGMT_ACK, optmgmt_ack); 917 COMMA (); 918 tprintf ("MGMT="); 919 printflags (transport_user_flags, m.optmgmt_ack.MGMT_flags, 920 "T_???"); 921 STRUCT (optmgmt_ack, OPT, print_optmgmt); 922 break; 923#endif 924#ifdef T_ORDREL_IND 925 case T_ORDREL_IND: /* orderly rel ind */ 926 GET (T_ORDREL_IND, ordrel_ind); 927 break; 928#endif 929#ifdef T_ADDR_REQ 930 case T_ADDR_REQ: /* address req */ 931 GET (T_ADDR_REQ, addr_req); 932 break; 933#endif 934#ifdef T_ADDR_ACK 935 case T_ADDR_ACK: /* address response */ 936 GET (T_ADDR_ACK, addr_ack); 937 ADDR (addr_ack, LOCADDR); 938 ADDR (addr_ack, REMADDR); 939 break; 940#endif 941 default: 942 dump: 943 c = -1; 944 printstr(tcp, addr, len); 945 break; 946 } 947 948 if (c >= 0) tprintf ("}"); 949 950#undef ADDR 951#undef COMMA 952#undef STRUCT 953 954 return 0; 955} 956 957 958#endif /* TI_BIND */ 959 960 961static int 962internal_stream_ioctl(tcp, arg) 963struct tcb *tcp; 964int arg; 965{ 966 struct strioctl si; 967 struct ioctlent *iop; 968 int in_and_out; 969 int timod = 0; 970#ifdef SI_GETUDATA 971 struct si_udata udata; 972#endif /* SI_GETUDATA */ 973 974 if (!arg) 975 return 0; 976 if (umove(tcp, arg, &si) < 0) { 977 if (entering(tcp)) 978 tprintf(", {...}"); 979 return 1; 980 } 981 if (entering(tcp)) { 982 iop = ioctl_lookup(si.ic_cmd); 983 if (iop) { 984 tprintf(", {ic_cmd=%s", iop->symbol); 985 while ((iop = ioctl_next_match(iop))) 986 tprintf(" or %s", iop->symbol); 987 } else 988 tprintf(", {ic_cmd=%#x", si.ic_cmd); 989 if (si.ic_timout == INFTIM) 990 tprintf(", ic_timout=INFTIM, "); 991 else 992 tprintf(" ic_timout=%d, ", si.ic_timout); 993 } 994 in_and_out = 1; 995 switch (si.ic_cmd) { 996#ifdef SI_GETUDATA 997 case SI_GETUDATA: 998 in_and_out = 0; 999 break; 1000#endif /* SI_GETUDATA */ 1001 } 1002 if (in_and_out) { 1003 if (entering(tcp)) 1004 tprintf("/* in */ "); 1005 else 1006 tprintf(", /* out */ "); 1007 } 1008 if (in_and_out || entering(tcp)) 1009 tprintf("ic_len=%d, ic_dp=", si.ic_len); 1010 switch (si.ic_cmd) { 1011#ifdef TI_BIND 1012 case TI_BIND: 1013 /* in T_BIND_REQ, out T_BIND_ACK */ 1014 ++timod; 1015 if (entering(tcp)) { 1016 print_transport_message (tcp, 1017 T_BIND_REQ, 1018 si.ic_dp, si.ic_len); 1019 } 1020 else { 1021 print_transport_message (tcp, 1022 T_BIND_ACK, 1023 si.ic_dp, si.ic_len); 1024 } 1025 break; 1026#endif /* TI_BIND */ 1027#ifdef TI_UNBIND 1028 case TI_UNBIND: 1029 /* in T_UNBIND_REQ, out T_OK_ACK */ 1030 ++timod; 1031 if (entering(tcp)) { 1032 print_transport_message (tcp, 1033 T_UNBIND_REQ, 1034 si.ic_dp, si.ic_len); 1035 } 1036 else { 1037 print_transport_message (tcp, 1038 T_OK_ACK, 1039 si.ic_dp, si.ic_len); 1040 } 1041 break; 1042#endif /* TI_UNBIND */ 1043#ifdef TI_GETINFO 1044 case TI_GETINFO: 1045 /* in T_INFO_REQ, out T_INFO_ACK */ 1046 ++timod; 1047 if (entering(tcp)) { 1048 print_transport_message (tcp, 1049 T_INFO_REQ, 1050 si.ic_dp, si.ic_len); 1051 } 1052 else { 1053 print_transport_message (tcp, 1054 T_INFO_ACK, 1055 si.ic_dp, si.ic_len); 1056 } 1057 break; 1058#endif /* TI_GETINFO */ 1059#ifdef TI_OPTMGMT 1060 case TI_OPTMGMT: 1061 /* in T_OPTMGMT_REQ, out T_OPTMGMT_ACK */ 1062 ++timod; 1063 if (entering(tcp)) { 1064 print_transport_message (tcp, 1065 T_OPTMGMT_REQ, 1066 si.ic_dp, si.ic_len); 1067 } 1068 else { 1069 print_transport_message (tcp, 1070 T_OPTMGMT_ACK, 1071 si.ic_dp, si.ic_len); 1072 } 1073 break; 1074#endif /* TI_OPTMGMT */ 1075#ifdef SI_GETUDATA 1076 case SI_GETUDATA: 1077 if (entering(tcp)) 1078 break; 1079#if 0 1080 tprintf("struct si_udata "); 1081#endif 1082 if (umove(tcp, (int) si.ic_dp, &udata) < 0) 1083 tprintf("{...}"); 1084 else { 1085 tprintf("{tidusize=%d, addrsize=%d, ", 1086 udata.tidusize, udata.addrsize); 1087 tprintf("optsize=%d, etsdusize=%d, ", 1088 udata.optsize, udata.etsdusize); 1089 tprintf("servtype=%d, so_state=%d, ", 1090 udata.servtype, udata.so_state); 1091 tprintf("so_options=%d", udata.so_options); 1092#if 0 1093 tprintf(", tsdusize=%d", udata.tsdusize); 1094#endif 1095 tprintf("}"); 1096 } 1097 break; 1098#endif /* SI_GETUDATA */ 1099 default: 1100 printstr(tcp, (long) si.ic_dp, si.ic_len); 1101 break; 1102 } 1103 if (exiting(tcp)) { 1104 tprintf("}"); 1105 if (timod && tcp->u_rval) { 1106 tcp->auxstr = xlookup (tli_errors, tcp->u_rval); 1107 return RVAL_STR + 1; 1108 } 1109 } 1110 1111 return 1; 1112} 1113 1114int 1115stream_ioctl(tcp, code, arg) 1116struct tcb *tcp; 1117int code, arg; 1118{ 1119#ifdef I_LIST 1120 int i; 1121#endif 1122 int val; 1123#ifdef I_FLUSHBAND 1124 struct bandinfo bi; 1125#endif 1126 struct strpeek sp; 1127 struct strfdinsert sfi; 1128 struct strrecvfd srf; 1129#ifdef I_LIST 1130 struct str_list sl; 1131#endif 1132 1133 /* I_STR is a special case because the data is read & written. */ 1134 if (code == I_STR) 1135 return internal_stream_ioctl(tcp, arg); 1136 if (entering(tcp)) 1137 return 0; 1138 1139 switch (code) { 1140 case I_PUSH: 1141 case I_LOOK: 1142 case I_FIND: 1143 /* arg is a string */ 1144 tprintf(", "); 1145 printpath(tcp, arg); 1146 return 1; 1147 case I_POP: 1148 /* doesn't take an argument */ 1149 return 1; 1150 case I_FLUSH: 1151 /* argument is an option */ 1152 tprintf(", "); 1153 printxval(stream_flush_options, arg, "FLUSH???"); 1154 return 1; 1155#ifdef I_FLUSHBAND 1156 case I_FLUSHBAND: 1157 /* argument is a pointer to a bandinfo struct */ 1158 if (umove(tcp, arg, &bi) < 0) 1159 tprintf(", {...}"); 1160 else { 1161 tprintf(", {bi_pri=%d, bi_flag=", bi.bi_pri); 1162 printflags(stream_flush_options, bi.bi_flag, "FLUSH???"); 1163 tprintf("}"); 1164 } 1165 return 1; 1166#endif /* I_FLUSHBAND */ 1167 case I_SETSIG: 1168 /* argument is a set of flags */ 1169 tprintf(", "); 1170 printflags(stream_setsig_flags, arg, "S_???"); 1171 return 1; 1172 case I_GETSIG: 1173 /* argument is a pointer to a set of flags */ 1174 if (syserror(tcp)) 1175 return 0; 1176 tprintf(", ["); 1177 if (umove(tcp, arg, &val) < 0) 1178 tprintf("?"); 1179 else 1180 printflags(stream_setsig_flags, val, "S_???"); 1181 tprintf("]"); 1182 return 1; 1183 case I_PEEK: 1184 /* argument is a pointer to a strpeek structure */ 1185 if (syserror(tcp) || !arg) 1186 return 0; 1187 if (umove(tcp, arg, &sp) < 0) { 1188 tprintf(", {...}"); 1189 return 1; 1190 } 1191 tprintf(", {ctlbuf="); 1192 printstrbuf(tcp, &sp.ctlbuf, 1); 1193 tprintf(", databuf="); 1194 printstrbuf(tcp, &sp.databuf, 1); 1195 tprintf(", flags="); 1196 printflags(msgflags, sp.flags, "RS_???"); 1197 tprintf("}"); 1198 return 1; 1199 case I_SRDOPT: 1200 /* argument is an option with flags */ 1201 tprintf(", "); 1202 printxval(stream_read_options, arg & RMODEMASK, "R???"); 1203 addflags(stream_read_flags, arg & ~RMODEMASK); 1204 return 1; 1205 case I_GRDOPT: 1206 /* argument is an pointer to an option with flags */ 1207 if (syserror(tcp)) 1208 return 0; 1209 tprintf(", ["); 1210 if (umove(tcp, arg, &val) < 0) 1211 tprintf("?"); 1212 else { 1213 printxval(stream_read_options, 1214 arg & RMODEMASK, "R???"); 1215 addflags(stream_read_flags, arg & ~RMODEMASK); 1216 } 1217 tprintf("]"); 1218 return 1; 1219 case I_NREAD: 1220#ifdef I_GETBAND 1221 case I_GETBAND: 1222#endif 1223#ifdef I_SETCLTIME 1224 case I_SETCLTIME: 1225#endif 1226#ifdef I_GETCLTIME 1227 case I_GETCLTIME: 1228#endif 1229 /* argument is a pointer to a decimal integer */ 1230 if (syserror(tcp)) 1231 return 0; 1232 tprintf(", "); 1233 printnum(tcp, arg, "%d"); 1234 return 1; 1235 case I_FDINSERT: 1236 /* argument is a pointer to a strfdinsert structure */ 1237 if (syserror(tcp) || !arg) 1238 return 0; 1239 if (umove(tcp, arg, &sfi) < 0) { 1240 tprintf(", {...}"); 1241 return 1; 1242 } 1243 tprintf(", {ctlbuf="); 1244 printstrbuf(tcp, &sfi.ctlbuf, 1); 1245 tprintf(", databuf="); 1246 printstrbuf(tcp, &sfi.databuf, 1); 1247 tprintf(", flags="); 1248 printflags(msgflags, sfi.flags, "RS_???"); 1249 tprintf(", filedes=%d, offset=%d}", sfi.fildes, sfi.offset); 1250 return 1; 1251#ifdef I_SWROPT 1252 case I_SWROPT: 1253 /* argument is a set of flags */ 1254 tprintf(", "); 1255 printflags(stream_write_flags, arg, "SND???"); 1256 return 1; 1257#endif /* I_SWROPT */ 1258#ifdef I_GWROPT 1259 case I_GWROPT: 1260 /* argument is an pointer to an option with flags */ 1261 if (syserror(tcp)) 1262 return 0; 1263 tprintf(", ["); 1264 if (umove(tcp, arg, &val) < 0) 1265 tprintf("?"); 1266 else 1267 printflags(stream_write_flags, arg, "SND???"); 1268 tprintf("]"); 1269 return 1; 1270#endif /* I_GWROPT */ 1271 case I_SENDFD: 1272#ifdef I_CKBAND 1273 case I_CKBAND: 1274#endif 1275#ifdef I_CANPUT 1276 case I_CANPUT: 1277#endif 1278 case I_LINK: 1279 case I_UNLINK: 1280 case I_PLINK: 1281 case I_PUNLINK: 1282 /* argument is a decimal integer */ 1283 tprintf(", %d", arg); 1284 return 1; 1285 case I_RECVFD: 1286 /* argument is a pointer to a strrecvfd structure */ 1287 if (syserror(tcp) || !arg) 1288 return 0; 1289 if (umove(tcp, arg, &srf) < 0) { 1290 tprintf(", {...}"); 1291 return 1; 1292 } 1293 tprintf(", {fd=%d, uid=%lu, gid=%lu}", srf.fd, 1294 (unsigned long) srf.uid, (unsigned long) srf.gid); 1295 return 1; 1296#ifdef I_LIST 1297 case I_LIST: 1298 if (syserror(tcp)) 1299 return 0; 1300 if (arg == 0) { 1301 tprintf(", NULL"); 1302 return 1; 1303 } 1304 if (umove(tcp, arg, &sl) < 0) { 1305 tprintf(", {...}"); 1306 return 1; 1307 } 1308 tprintf(", {sl_nmods=%d, sl_modlist=[", sl.sl_nmods); 1309 for (i = 0; i < tcp->u_rval; i++) { 1310 if (i) 1311 tprintf(", "); 1312 printpath(tcp, (int) sl.sl_modlist[i].l_name); 1313 } 1314 tprintf("]}"); 1315 return 1; 1316#endif /* I_LIST */ 1317#ifdef I_ATMARK 1318 case I_ATMARK: 1319 tprintf(", "); 1320 printxval(stream_atmark_options, arg, "???MARK"); 1321 return 1; 1322#endif /* I_ATMARK */ 1323 default: 1324 return 0; 1325 } 1326} 1327 1328#endif /* !LINUX && !FREEBSD */ 1329 1330#endif /* HAVE_SYS_STREAM_H || LINUX || FREEBSD */ 1331