| /* |
| * dsock.c - SCO UnixWare socket processing functions for lsof |
| */ |
| |
| |
| /* |
| * Copyright 1996 Purdue Research Foundation, West Lafayette, Indiana |
| * 47907. All rights reserved. |
| * |
| * Written by Victor A. Abell |
| * |
| * This software is not subject to any license of the American Telephone |
| * and Telegraph Company or the Regents of the University of California. |
| * |
| * Permission is granted to anyone to use this software for any purpose on |
| * any computer system, and to alter it and redistribute it freely, subject |
| * to the following restrictions: |
| * |
| * 1. Neither the authors nor Purdue University are responsible for any |
| * consequences of the use of this software. |
| * |
| * 2. The origin of this software must not be misrepresented, either by |
| * explicit claim or by omission. Credit to the authors and Purdue |
| * University must appear in documentation and sources. |
| * |
| * 3. Altered versions must be plainly marked as such, and must not be |
| * misrepresented as being the original software. |
| * |
| * 4. This notice may not be removed or altered. |
| */ |
| |
| #ifndef lint |
| static char copyright[] = |
| "@(#) Copyright 1996 Purdue Research Foundation.\nAll rights reserved.\n"; |
| static char *rcsid = "$Id: dsock.c,v 1.16 2005/08/13 16:21:41 abe Exp $"; |
| #endif |
| |
| |
| #define TCPSTATES /* activate tcpstates[] */ |
| #include "lsof.h" |
| |
| |
| /* |
| * Local function prototypes |
| */ |
| |
| #if UNIXWAREV>=70101 && UNIXWAREV<70103 |
| _PROTOTYPE(static struct sockaddr_un *find_unix_sockaddr_un,(KA_T ka)); |
| #endif /* UNIXWAREV>=70101 && UNIXWAREV<70103 */ |
| |
| |
| /* |
| * print_tcptpi() - print TCP/TPI info |
| */ |
| |
| void |
| print_tcptpi(nl) |
| int nl; /* 1 == '\n' required */ |
| { |
| char buf[128]; |
| char *cp = (char *)NULL; |
| int ps = 0; |
| int s; |
| |
| if (Ftcptpi & TCPTPI_STATE) { |
| s = Lf->lts.state.i; |
| switch (Lf->lts.type) { |
| case 0: |
| if (s < 0 || s >= TCP_NSTATES) { |
| (void) snpf(buf, sizeof(buf), "UNKNOWN_TCP_STATE_%d", s); |
| cp = buf; |
| } else |
| cp = tcpstates[s]; |
| break; |
| case 1: |
| switch (s) { |
| case TS_UNBND: |
| cp = "TS_UNBND"; |
| break; |
| case TS_WACK_BREQ: |
| cp = "TS_WACK_BREQ"; |
| break; |
| case TS_WACK_UREQ: |
| cp = "TS_WACK_UREQ"; |
| break; |
| case TS_IDLE: |
| cp = "TS_IDLE"; |
| break; |
| case TS_WACK_OPTREQ: |
| cp = "TS_WACK_OPTREQ"; |
| break; |
| case TS_WACK_CREQ: |
| cp = "TS_WACK_CREQ"; |
| break; |
| case TS_WCON_CREQ: |
| cp = "TS_WCON_CREQ"; |
| break; |
| case TS_WRES_CIND: |
| cp = "TS_WRES_CIND"; |
| break; |
| case TS_WACK_CRES: |
| cp = "TS_WACK_CRES"; |
| break; |
| case TS_DATA_XFER: |
| cp = "TS_DATA_XFER"; |
| break; |
| case TS_WIND_ORDREL: |
| cp = "TS_WIND_ORDREL"; |
| break; |
| case TS_WREQ_ORDREL: |
| cp = "TS_WREQ_ORDREL"; |
| break; |
| case TS_WACK_DREQ6: |
| cp = "TS_WACK_DREQ6"; |
| break; |
| case TS_WACK_DREQ7: |
| cp = "TS_WACK_DREQ7"; |
| break; |
| case TS_WACK_DREQ9: |
| cp = "TS_WACK_DREQ9"; |
| break; |
| case TS_WACK_DREQ10: |
| cp = "TS_WACK_DREQ10"; |
| break; |
| case TS_WACK_DREQ11: |
| cp = "TS_WACK_DREQ11"; |
| break; |
| default: |
| (void) snpf(buf, sizeof(buf), "UNKNOWN_TPI_STATE_%d", s); |
| cp = buf; |
| } |
| } |
| if (cp) { |
| if (Ffield) |
| (void) printf("%cST=%s%c", LSOF_FID_TCPTPI, cp, Terminator); |
| else { |
| putchar('('); |
| (void) fputs(cp, stdout); |
| } |
| ps++; |
| } |
| } |
| |
| # if defined(HASTCPTPIQ) |
| if (Ftcptpi & TCPTPI_QUEUES) { |
| if (Lf->lts.rqs) { |
| if (Ffield) |
| putchar(LSOF_FID_TCPTPI); |
| else { |
| if (ps) |
| putchar(' '); |
| else |
| putchar('('); |
| } |
| (void) printf("QR=%lu", Lf->lts.rq); |
| if (Ffield) |
| putchar(Terminator); |
| ps++; |
| } |
| if (Lf->lts.sqs) { |
| if (Ffield) |
| putchar(LSOF_FID_TCPTPI); |
| else { |
| if (ps) |
| putchar(' '); |
| else |
| putchar('('); |
| } |
| (void) printf("QS=%lu", Lf->lts.sq); |
| if (Ffield) |
| putchar(Terminator); |
| ps++; |
| } |
| } |
| # endif /* defined(HASTCPTPIQ) */ |
| |
| #if defined(HASSOOPT) |
| if (Ftcptpi & TCPTPI_FLAGS) { |
| int opt; |
| |
| if ((opt = Lf->lts.opt) |
| || Lf->lts.pqlens || Lf->lts.qlens || Lf->lts.qlims |
| || Lf->lts.rbszs || Lf->lts.sbsz |
| ) { |
| char sep = ' '; |
| |
| if (Ffield) |
| sep = LSOF_FID_TCPTPI; |
| else if (!ps) |
| sep = '('; |
| (void) printf("%cSO", sep); |
| ps++; |
| sep = '='; |
| |
| # if defined(SO_ACCEPTCONN) |
| if (opt & SO_ACCEPTCONN) { |
| (void) printf("%cACCEPTCONN", sep); |
| opt &= ~SO_ACCEPTCONN; |
| sep = ','; |
| } |
| # endif /* defined(SO_ACCEPTCONN) */ |
| |
| # if defined(SO_BROADCAST) |
| if (opt & SO_BROADCAST) { |
| (void) printf("%cBROADCAST", sep); |
| opt &= ~SO_BROADCAST; |
| sep = ','; |
| } |
| # endif /* defined(SO_BROADCAST) */ |
| |
| # if defined(SO_DEBUG) |
| if (opt & SO_DEBUG) { |
| (void) printf("%cDEBUG", sep); |
| opt &= ~ SO_DEBUG; |
| sep = ','; |
| } |
| # endif /* defined(SO_DEBUG) */ |
| |
| # if defined(SO_DONTROUTE) |
| if (opt & SO_DONTROUTE) { |
| (void) printf("%cDONTROUTE", sep); |
| opt &= ~SO_DONTROUTE; |
| sep = ','; |
| } |
| # endif /* defined(SO_DONTROUTE) */ |
| |
| # if defined(SO_IMASOCKET) |
| if (opt & SO_IMASOCKET) { |
| (void) printf("%cIMASOCKET", sep); |
| opt &= ~SO_IMASOCKET; |
| sep = ','; |
| } |
| # endif /* defined(SO_IMASOCKET) */ |
| |
| # if defined(SO_KEEPALIVE) |
| if (opt & SO_KEEPALIVE) { |
| (void) printf("%cKEEPALIVE", sep); |
| opt &= ~SO_KEEPALIVE; |
| sep = ','; |
| } |
| # endif /* defined(SO_KEEPALIVE) */ |
| |
| # if defined(SO_LINGER) |
| if (opt & SO_LINGER) { |
| (void) printf("%cLINGER", sep); |
| if (Lf->lts.ltm) |
| (void) printf("=%d", Lf->lts.ltm); |
| opt &= ~SO_LINGER; |
| sep = ','; |
| } |
| # endif /* defined(SO_LINGER) */ |
| |
| # if defined(SO_LISTENING) |
| if (opt & SO_LISTENING) { |
| (void) printf("%cLISTENING", sep); |
| opt &= ~SO_LISTENING; |
| sep = ','; |
| } |
| # endif /* defined(SO_LISTENING) */ |
| |
| # if defined(SO_MGMT) |
| if (opt & SO_MGMT) { |
| (void) printf("%cMGMT", sep); |
| opt &= ~SO_MGMT; |
| sep = ','; |
| } |
| # endif /* defined(SO_MGMT) */ |
| |
| # if defined(SO_OOBINLINE) |
| if (opt & SO_OOBINLINE) { |
| (void) printf("%cOOBINLINE", sep); |
| opt &= ~SO_OOBINLINE; |
| sep = ','; |
| } |
| # endif /* defined(SO_OOBINLINE) */ |
| |
| # if defined(SO_ORDREL) |
| if (opt & SO_ORDREL) { |
| (void) printf("%cORDREL", sep); |
| opt &= ~SO_ORDREL; |
| sep = ','; |
| } |
| # endif /* defined(SO_ORDREL) */ |
| |
| # if defined(SO_PARALLELSVR) |
| if (opt & SO_PARALLELSVR) { |
| (void) printf("%cPARALLELSVR", sep); |
| opt &= ~SO_PARALLELSVR; |
| sep = ','; |
| } |
| # endif /* defined(SO_PARALLELSVR) */ |
| |
| if (Lf->lts.pqlens) { |
| (void) printf("%cPQLEN=%u", sep, Lf->lts.pqlen); |
| sep = ','; |
| } |
| if (Lf->lts.qlens) { |
| (void) printf("%cQLEN=%u", sep, Lf->lts.qlen); |
| sep = ','; |
| } |
| if (Lf->lts.qlims) { |
| (void) printf("%cQLIM=%u", sep, Lf->lts.qlim); |
| sep = ','; |
| } |
| if (Lf->lts.rbszs) { |
| (void) printf("%cRCVBUF=%lu", sep, Lf->lts.rbsz); |
| sep = ','; |
| } |
| |
| # if defined(SO_RDWR) |
| if (opt & SO_RDWR) { |
| (void) printf("%cRDWR", sep); |
| opt &= ~SO_RDWR; |
| sep = ','; |
| } |
| # endif /* defined(SO_RDWR) */ |
| |
| # if defined(SO_REUSEADDR) |
| if (opt & SO_REUSEADDR) { |
| (void) printf("%cREUSEADDR", sep); |
| opt &= ~SO_REUSEADDR; |
| sep = ','; |
| } |
| # endif /* defined(SO_REUSEADDR) */ |
| |
| # if defined(SO_REUSEPORT) |
| if (opt & SO_REUSEPORT) { |
| (void) printf("%cREUSEPORT", sep); |
| opt &= ~SO_REUSEPORT; |
| sep = ','; |
| } |
| # endif /* defined(SO_REUSEPORT) */ |
| |
| # if defined(SO_SEMA) |
| if (opt & SO_SEMA) { |
| (void) printf("%cSEMA", sep); |
| opt &= ~SO_SEMA; |
| sep = ','; |
| } |
| # endif /* defined(SO_SEMA) */ |
| |
| if (Lf->lts.sbszs) { |
| (void) printf("%cSNDBUF=%lu", sep, Lf->lts.sbsz); |
| sep = ','; |
| } |
| |
| # if defined(SO_USELOOPBACK) |
| if (opt & SO_USELOOPBACK) { |
| (void) printf("%cUSELOOPBACK", sep); |
| opt &= ~SO_USELOOPBACK; |
| sep = ','; |
| } |
| # endif /* defined(SO_USELOOPBACK) */ |
| |
| if (opt) |
| (void) printf("%cUNKNOWN=%#x", sep, opt); |
| if (Ffield) |
| putchar(Terminator); |
| } |
| } |
| #endif /* defined(HASSOOPT) */ |
| |
| #if defined(HASSOSTATE) |
| if (Ftcptpi & TCPTPI_FLAGS) { |
| int ss; |
| |
| if ((ss = Lf->lts.ss)) { |
| char sep = ' '; |
| |
| if (Ffield) |
| sep = LSOF_FID_TCPTPI; |
| else if (!ps) |
| sep = '('; |
| (void) printf("%cSS", sep); |
| ps++; |
| sep = '='; |
| |
| # if defined(SS_ASYNC) |
| if (ss & SS_ASYNC) { |
| (void) printf("%cASYNC", sep); |
| ss &= ~SS_ASYNC; |
| sep = ','; |
| } |
| # endif /* defined(SS_ASYNC) */ |
| |
| # if defined(SS_CANTRCVMORE) |
| if (ss & SS_CANTRCVMORE) { |
| (void) printf("%cCANTRCVMORE", sep); |
| ss &= ~SS_CANTRCVMORE; |
| sep = ','; |
| } |
| # endif /* defined(SS_CANTRCVMORE) */ |
| |
| # if defined(SS_CANTSENDMORE) |
| if (ss & SS_CANTSENDMORE) { |
| (void) printf("%cCANTSENDMORE", sep); |
| ss &= ~SS_CANTSENDMORE; |
| sep = ','; |
| } |
| # endif /* defined(SS_CANTSENDMORE) */ |
| |
| # if defined(SS_IGNERR) |
| if (ss & SS_IGNERR) { |
| (void) printf("%cIGNERR", sep); |
| ss &= ~SS_IGNERR; |
| sep = ','; |
| } |
| # endif /* defined(SS_IGNERR) */ |
| |
| # if defined(SS_ISBOUND) |
| if (ss & SS_ISBOUND) { |
| (void) printf("%cISBOUND", sep); |
| ss &= ~SS_ISBOUND; |
| sep = ','; |
| } |
| # endif /* defined(SS_ISBOUND) */ |
| |
| # if defined(SS_ISCONNECTED) |
| if (ss & SS_ISCONNECTED) { |
| (void) printf("%cISCONNECTED", sep); |
| ss &= ~SS_ISCONNECTED; |
| sep = ','; |
| } |
| # endif /* defined(SS_ISCONNECTED) */ |
| |
| # if defined(SS_ISCONNECTING) |
| if (ss & SS_ISCONNECTING) { |
| (void) printf("%cISCONNECTING", sep); |
| ss &= ~SS_ISCONNECTING; |
| sep = ','; |
| } |
| # endif /* defined(SS_ISCONNECTING) */ |
| |
| # if defined(SS_ISDISCONNECTING) |
| if (ss & SS_ISDISCONNECTING) { |
| (void) printf("%cISDISCONNECTING", sep); |
| ss &= ~SS_ISDISCONNECTING; |
| sep = ','; |
| } |
| # endif /* defined(SS_ISDISCONNECTING) */ |
| |
| # if defined(SS_NBIO) |
| if (ss & SS_NBIO) { |
| (void) printf("%cNBIO", sep); |
| ss &= ~SS_NBIO; |
| sep = ','; |
| } |
| # endif /* defined(SS_NBIO) */ |
| |
| # if defined(SS_NODELETE) |
| if (ss & SS_NODELETE) { |
| (void) printf("%cNODELETE", sep); |
| ss &= ~SS_NODELETE; |
| sep = ','; |
| } |
| # endif /* defined(SS_NODELETE) */ |
| |
| # if defined(SS_NOGHOST) |
| if (ss & SS_NOGHOST) { |
| (void) printf("%cNOGHOST", sep); |
| ss &= ~SS_NOGHOST; |
| sep = ','; |
| } |
| # endif /* defined(SS_NOGHOST) */ |
| |
| # if defined(SS_NOINPUT) |
| if (ss & SS_NOINPUT) { |
| (void) printf("%cNOINPUT", sep); |
| ss &= ~SS_NOINPUT; |
| sep = ','; |
| } |
| # endif /* defined(SS_NOINPUT) */ |
| |
| # if defined(SS_NOFDREF) |
| if (ss & SS_NOFDREF) { |
| (void) printf("%cNOFDREF", sep); |
| ss &= ~SS_NOFDREF; |
| sep = ','; |
| } |
| # endif /* defined(SS_NOFDREF) */ |
| |
| # if defined(SS_PRIV) |
| if (ss & SS_PRIV) { |
| (void) printf("%cPRIV", sep); |
| ss &= ~SS_PRIV; |
| sep = ','; |
| } |
| # endif /* defined(SS_PRIV) */ |
| |
| # if defined(SS_RCVATMARK) |
| if (ss & SS_RCVATMARK) { |
| (void) printf("%cRCVATMARK", sep); |
| ss &= ~SS_RCVATMARK; |
| sep = ','; |
| } |
| # endif /* defined(SS_RCVATMARK) */ |
| |
| # if defined(SS_SETRCV) |
| if (ss & SS_SETRCV) { |
| (void) printf("%cSETRCV", sep); |
| ss &= ~SS_SETRCV; |
| sep = ','; |
| } |
| # endif /* defined(SS_SETRCV) */ |
| |
| # if defined(SS_SETSND) |
| if (ss & SS_SETSND) { |
| (void) printf("%cSETSND", sep); |
| ss &= ~SS_SETSND; |
| sep = ','; |
| } |
| # endif /* defined(SS_SETSND) */ |
| |
| # if defined(SS_ZOMBIE) |
| if (ss & SS_ZOMBIE) { |
| (void) printf("%cZOMBIE", sep); |
| ss &= ~SS_ZOMBIE; |
| sep = ','; |
| } |
| # endif /* defined(SS_ZOMBIE) */ |
| |
| if (ss) |
| (void) printf("%cUNKNOWN=%#x", sep, ss); |
| if (Ffield) |
| putchar(Terminator); |
| } |
| } |
| #endif /* defined(HASSOSTATE) */ |
| |
| #if defined(HASTCPOPT) |
| if (Ftcptpi & TCPTPI_FLAGS) { |
| int topt; |
| |
| if ((topt = Lf->lts.topt) || Lf->lts.msss) { |
| char sep = ' '; |
| |
| if (Ffield) |
| sep = LSOF_FID_TCPTPI; |
| else if (!ps) |
| sep = '('; |
| (void) printf("%cTF", sep); |
| ps++; |
| sep = '='; |
| |
| # if defined(TF_ACKNOW) |
| if (topt & TF_ACKNOW) { |
| (void) printf("%cACKNOW", sep); |
| topt &= ~TF_ACKNOW; |
| sep = ','; |
| } |
| # endif /* defined(TF_ACKNOW) */ |
| |
| # if defined(TF_DELACK) |
| if (topt & TF_DELACK) { |
| (void) printf("%cDELACK", sep); |
| topt &= ~TF_DELACK; |
| sep = ','; |
| } |
| # endif /* defined(TF_DELACK) */ |
| |
| # if defined(TF_HAVEACKED) |
| if (topt & TF_HAVEACKED) { |
| (void) printf("%cHAVEACKED", sep); |
| topt &= ~TF_HAVEACKED; |
| sep = ','; |
| } |
| # endif /* defined(TF_HAVEACKED) */ |
| |
| # if defined(TF_HAVECLOSED) |
| if (topt & TF_HAVECLOSED) { |
| (void) printf("%cHAVECLOSED", sep); |
| topt &= ~TF_HAVECLOSED; |
| sep = ','; |
| } |
| # endif /* defined(TF_HAVECLOSED) */ |
| |
| # if defined(TF_IOLOCK) |
| if (topt & TF_IOLOCK) { |
| (void) printf("%cIOLOCK", sep); |
| topt &= ~TF_IOLOCK; |
| sep = ','; |
| } |
| # endif /* defined(TF_IOLOCK) */ |
| |
| if (Lf->lts.msss) { |
| (void) printf("%cMSS=%lu", sep, Lf->lts.mss); |
| sep = ','; |
| } |
| |
| # if defined(TF_MAXSEG_TSTMP) |
| if (topt & TF_MAXSEG_TSTMP) { |
| (void) printf("%cMAXSEG_TSTMP", sep); |
| topt &= ~TF_MAXSEG_TSTMP; |
| sep = ','; |
| } |
| # endif /* defined(TF_MAXSEG_TSTMP) */ |
| |
| # if defined(TF_NEEDCLOSE) |
| if (topt & TF_NEEDCLOSE) { |
| (void) printf("%cNEEDCLOSE", sep); |
| topt &= ~TF_NEEDCLOSE; |
| sep = ','; |
| } |
| # endif /* defined(TF_NEEDCLOSE) */ |
| |
| # if defined(TF_NEEDIN) |
| if (topt & TF_NEEDIN) { |
| (void) printf("%cNEEDIN", sep); |
| topt &= ~TF_NEEDIN; |
| sep = ','; |
| } |
| # endif /* defined(TF_NEEDIN) */ |
| |
| # if defined(TF_NEEDOUT) |
| if (topt & TF_NEEDOUT) { |
| (void) printf("%cNEEDOUT", sep); |
| topt &= ~TF_NEEDOUT; |
| sep = ','; |
| } |
| # endif /* defined(TF_NEEDOUT) */ |
| |
| # if defined(TF_NEEDTIMER) |
| if (topt & TF_NEEDTIMER) { |
| (void) printf("%cNEEDTIMER", sep); |
| topt &= ~TF_NEEDTIMER; |
| sep = ','; |
| } |
| # endif /* defined(TF_NEEDTIMER) */ |
| |
| # if defined(TF_NODELACK) |
| if (topt & TF_NODELACK) { |
| (void) printf("%cNODELACK", sep); |
| topt &= ~TF_NODELACK; |
| sep = ','; |
| } |
| # endif /* defined(TF_NODELACK) */ |
| |
| # if defined(TF_NODELAY) |
| if (topt & TF_NODELAY) { |
| (void) printf("%cNODELAY", sep); |
| topt &= ~TF_NODELAY; |
| sep = ','; |
| } |
| # endif /* defined(TF_NODELAY) */ |
| |
| # if defined(TF_NOOPT) |
| if (topt & TF_NOOPT) { |
| (void) printf("%cNOOPT", sep); |
| topt &= ~TF_NOOPT; |
| sep = ','; |
| } |
| # endif /* defined(TF_NOOPT) */ |
| |
| # if defined(TF_RCVD_SCALE) |
| if (topt & TF_RCVD_SCALE) { |
| (void) printf("%cRCVD_SCALE", sep); |
| topt &= ~TF_RCVD_SCALE; |
| sep = ','; |
| } |
| # endif /* defined(TF_RCVD_SCALE) */ |
| |
| # if defined(TF_RCVD_TSTMP) |
| if (topt & TF_RCVD_TSTMP) { |
| (void) printf("%cRCVD_TSTMP", sep); |
| topt &= ~TF_RCVD_TSTMP; |
| sep = ','; |
| } |
| # endif /* defined(TF_RCVD_TSTMP) */ |
| |
| # if defined(TF_REQ_SCALE) |
| if (topt & TF_REQ_SCALE) { |
| (void) printf("%cREQ_SCALE", sep); |
| topt &= ~TF_REQ_SCALE; |
| sep = ','; |
| } |
| # endif /* defined(TF_REQ_SCALE) */ |
| |
| # if defined(TF_REQ_TSTMP) |
| if (topt & TF_REQ_TSTMP) { |
| (void) printf("%cREQ_TSTMP", sep); |
| topt &= ~TF_REQ_TSTMP; |
| sep = ','; |
| } |
| # endif /* defined(TF_REQ_TSTMP) */ |
| |
| # if defined(TF_SACK_PERMIT) |
| if (topt & TF_SACK_PERMIT) { |
| (void) printf("%cSACK_PERMIT", sep); |
| topt &= ~TF_SACK_PERMIT; |
| sep = ','; |
| } |
| # endif /* defined(TF_SACK_PERMIT) */ |
| |
| # if defined(TF_SENTFIN) |
| if (topt & TF_SENTFIN) { |
| (void) printf("%cSENTFIN", sep); |
| topt &= ~TF_SENTFIN; |
| sep = ','; |
| } |
| # endif /* defined(TF_SENTFIN) */ |
| |
| # if defined(TF_USERCLOSE) |
| if (topt & TF_USERCLOSE) { |
| (void) printf("%cUSERCLOSE", sep); |
| topt &= ~TF_USERCLOSE; |
| sep = ','; |
| } |
| # endif /* defined(TF_USERCLOSE) */ |
| |
| if (topt) |
| (void) printf("%cUNKNOWN=%#x", sep, topt); |
| if (Ffield) |
| putchar(Terminator); |
| } |
| } |
| #endif /* defined(HASTCPOPT) */ |
| |
| # if defined(HASTCPTPIW) |
| if (Ftcptpi & TCPTPI_WINDOWS) { |
| if (Lf->lts.rws) { |
| if (Ffield) |
| putchar(LSOF_FID_TCPTPI); |
| else { |
| if (ps) |
| putchar(' '); |
| else |
| putchar('('); |
| } |
| (void) printf("WR=%lu", Lf->lts.rw); |
| if (Ffield) |
| putchar(Terminator); |
| ps++; |
| } |
| if (Lf->lts.wws) { |
| if (Ffield) |
| putchar(LSOF_FID_TCPTPI); |
| else { |
| if (ps) |
| putchar(' '); |
| else |
| putchar('('); |
| } |
| (void) printf("WW=%lu", Lf->lts.ww); |
| if (Ffield) |
| putchar(Terminator); |
| ps++; |
| } |
| } |
| # endif /* defined(HASTCPTPIW) */ |
| |
| if (!Ffield && ps) |
| putchar(')'); |
| if (nl) |
| putchar('\n'); |
| } |
| |
| |
| /* |
| * process_socket() - process socket |
| */ |
| |
| void |
| process_socket(pr, q) |
| char *pr; /* protocol name */ |
| struct queue *q; /* queue at end of stream */ |
| { |
| unsigned char *fa = (unsigned char *)NULL; |
| int fp, ipv, lp; |
| struct inpcb inp; |
| unsigned char *la = (unsigned char *)NULL; |
| struct tcpcb t; |
| int tcp = 0; |
| short ts = 0; |
| int udp = 0; |
| |
| /* |
| * Process protocol specification. |
| */ |
| Lf->inp_ty = 2; |
| (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%s", pr); |
| Lf->is_stream = 0; |
| if (strcasecmp(pr, "TCP") == 0) { |
| ipv = 4; |
| tcp = 1; |
| } else if (strcasecmp(pr, "UDP") == 0) { |
| ipv = 4; |
| udp = 1; |
| } |
| |
| #if defined(HASIPv6) |
| else if (strcasecmp(pr, "TCP6") == 0) { |
| ipv = 6; |
| tcp = 1; |
| Lf->iproto[3] = '\0'; |
| } else if (strcasecmp(pr, "UDP6") == 0) { |
| ipv = 6; |
| udp = 1; |
| Lf->iproto[3] = '\0'; |
| } |
| #endif /* defined(HASIPv6) */ |
| |
| if (Fnet && (tcp || udp)) { |
| if (!FnetTy || (FnetTy == ipv)) |
| Lf->sf |= SELNET; |
| } |
| |
| #if defined(HASIPv6) |
| (void) snpf(Lf->type, sizeof(Lf->type), (ipv == 6) ? "IPv6" : "IPv4"); |
| #else /* !defined(HASIPv6) */ |
| (void) snpf(Lf->type, sizeof(Lf->type), "inet"); |
| #endif /* defined(HASIPv6) */ |
| |
| /* |
| * The PCB address is found in the private data structure at the end |
| * of the queue. |
| */ |
| if (q->q_ptr) { |
| enter_dev_ch(print_kptr((KA_T)q->q_ptr, (char *)NULL, 0)); |
| if (tcp || udp) { |
| if (kread((KA_T)q->q_ptr, (char *)&inp, sizeof(inp))) { |
| (void) snpf(Namech, Namechl, "can't read inpcb from %s", |
| print_kptr((KA_T)q->q_ptr, (char *)NULL, 0)); |
| enter_nm(Namech); |
| return; |
| } |
| la = (unsigned char *)&inp.inp_laddr; |
| lp = (int)ntohs(inp.inp_lport); |
| if (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport != 0) { |
| fa = (unsigned char *)&inp.inp_faddr; |
| fp = (int)ntohs(inp.inp_fport); |
| } |
| if (fa || la) |
| (void) ent_inaddr(la, lp, fa, fp, AF_INET); |
| if (tcp) { |
| if (inp.inp_ppcb |
| && !kread((KA_T)inp.inp_ppcb, (char *)&t, sizeof(t))) { |
| ts = 1; |
| Lf->lts.type = 0; |
| Lf->lts.state.i = (int)t.t_state; |
| } |
| } else { |
| Lf->lts.type = 1; |
| Lf->lts.state.i = (int)inp.inp_tstate; |
| } |
| } else |
| enter_nm("no address for this protocol"); |
| } else |
| enter_nm("no address"); |
| /* |
| * Save size information. |
| */ |
| if (ts) { |
| if (Fsize) { |
| |
| #if UNIXWAREV>=70000 |
| #define t_outqsize t_qsize |
| #endif /* UNIXWAREV>=70000 */ |
| |
| if (Lf->access == 'r') |
| Lf->sz = (SZOFFTYPE)t.t_iqsize; |
| else if (Lf->access == 'w') |
| Lf->sz = (SZOFFTYPE)t.t_outqsize; |
| else |
| Lf->sz = (SZOFFTYPE)(t.t_iqsize + t.t_outqsize); |
| Lf->sz_def = 1; |
| |
| } else |
| Lf->off_def = 1; |
| |
| #if defined(HASTCPTPIQ) |
| Lf->lts.rq = (unsigned long)t.t_iqsize; |
| Lf->lts.sq = (unsigned long)t.t_outqsize; |
| Lf->lts.rqs = Lf->lts.sqs = 1; |
| #endif /* defined(HASTCPTPIQ) */ |
| |
| #if defined(HASSOOPT) |
| Lf->lts.opt = (unsigned int)inp.inp_protoopt; |
| Lf->lts.ltm = (unsigned int)inp.inp_linger; |
| Lf->lts.pqlen = (unsigned int)t.t_q0len; |
| Lf->lts.qlen = (unsigned int)t.t_qlen; |
| Lf->lts.qlim = (unsigned int)t.t_qlimit; |
| Lf->lts.rbsz = (unsigned long)inp.inp_rbufsize; |
| Lf->lts.sbsz = (unsigned long)inp.inp_sbufsize; |
| Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims = Lf->lts.rbszs |
| = Lf->lts.sbszs = (unsigned char)1; |
| #endif /* defined(HASSOOPT) */ |
| |
| #if defined(HASSOSTATE) |
| Lf->lts.ss = (unsigned int)inp.inp_state; |
| #endif /* defined(HASSOSTATE) */ |
| |
| #if defined(HASTCPOPT) |
| Lf->lts.mss = (unsigned long)t.t_maxseg; |
| Lf->lts.msss = (unsigned char)1; |
| Lf->lts.topt = (unsigned int)t.t_flags; |
| #endif /* defined(HASTCPOPT) */ |
| |
| } |
| else if (Fsize) { |
| Lf->sz = (SZOFFTYPE)q->q_count; |
| Lf->sz_def = 1; |
| } else |
| Lf->off_def = 1; |
| enter_nm(Namech); |
| return; |
| } |
| |
| |
| #if UNIXWAREV>=70101 |
| /* |
| * process_unix_sockstr() - process a UNIX socket stream, if applicable |
| */ |
| |
| int |
| process_unix_sockstr(v, na) |
| struct vnode *v; /* the stream's vnode */ |
| KA_T na; /* kernel vnode address */ |
| { |
| int as; |
| char *ep, tbuf[32], tbuf1[32], *ty; |
| KA_T ka, sa, sh; |
| struct stdata sd; |
| struct ss_socket ss; |
| size_t sz; |
| |
| # if UNIXWAREV<70103 |
| struct sockaddr_un *la, *ra; |
| # else /* UNIXWAREV>=70103 */ |
| struct sockaddr_un la, ra; |
| unsigned char las = 0; |
| unsigned char ras = 0; |
| int up = (int)(sizeof(la.sun_path) - 1); |
| /* |
| * It's serious if the sizeof(sun_path) in sockaddr_un isn't greater than zero. |
| */ |
| if (up < 0) { |
| (void) snpf(Namech, Namechl, "sizeof(sun_path) < 1 (%d)", up); |
| enter_nm(Namech); |
| return(1); |
| } |
| # endif /* UNIXWAREV<70103 */ |
| |
| /* |
| * Read the stream head, if possible. |
| */ |
| if (!(sh = (KA_T)v->v_stream)) |
| return(0); |
| if (readstdata(sh, &sd)) { |
| (void) snpf(Namech, Namechl, |
| "vnode at %s; can't read stream head at %s", |
| print_kptr(na, (char *)NULL, 0), |
| print_kptr(sh, tbuf, sizeof(tbuf))); |
| enter_nm(Namech); |
| return(1); |
| } |
| /* |
| * If the stream head has pointer to a socket, read the socket structure |
| */ |
| if (!(sa = (KA_T)sd.sd_socket)) |
| return(0); |
| if (kread(sa, (char *)&ss, sizeof(ss))) { |
| (void) snpf(Namech, Namechl, |
| "vnode at %s; stream head at %s; can't read socket at %s", |
| print_kptr(na, (char *)NULL, 0), |
| print_kptr(sh, tbuf, sizeof(tbuf)), |
| print_kptr(sa, tbuf1, sizeof(tbuf1))); |
| enter_nm(Namech); |
| return(1); |
| } |
| /* |
| * If the socket is bound to the PF_UNIX protocol family, process it as |
| * a UNIX socket. Otherwise, return and let the vnode be processed as a |
| * stream. |
| */ |
| if (ss.family != PF_UNIX) |
| return(0); |
| (void) snpf(Lf->type, sizeof(Lf->type), "unix"); |
| if (Funix) |
| Lf->sf |= SELUNX; |
| Lf->is_stream = 0; |
| if (!Fsize) |
| Lf->off_def = 1; |
| enter_dev_ch(print_kptr(sa, (char *)NULL, 0)); |
| /* |
| * Process the local address. |
| */ |
| |
| # if UNIXWAREV<70103 |
| if ((la = find_unix_sockaddr_un((KA_T)sd.sd_socket))) { |
| if (Sfile && is_file_named(la->sun_path, 0)) |
| Lf->sf = SELNM; |
| } |
| # else /* UNIXWAREV>=70103 */ |
| if (((as = (KA_T)ss.local_addrsz) > 0) && (ka = (KA_T)ss.local_addr)) |
| { |
| if (as > sizeof(la)) |
| as = (int)sizeof(la); |
| if (!kread(ka, (char *)&la, as)) { |
| la.sun_path[up] = '\0'; |
| if (la.sun_path[0]) { |
| las = 1; |
| if (Sfile && is_file_named(la.sun_path, 0)) |
| Lf->sf = SELNM; |
| } |
| } |
| } |
| # endif /* UNIXWAREV<70103 */ |
| |
| /* |
| * Process the remote address. |
| */ |
| |
| # if UNIXWAREV<70103 |
| if ((ra = find_unix_sockaddr_un((KA_T)ss.conn_ux))) { |
| if (Sfile && is_file_named(ra->sun_path, 0)) |
| Lf->sf = SELNM; |
| } |
| # else /* UNIXWAREV>=70103 */ |
| if (((as = (KA_T)ss.remote_addrsz) > 0) && (ka = (KA_T)ss.remote_addr)) |
| { |
| if (as > sizeof(la)) |
| as = (int)sizeof(ra); |
| if (!kread(ka, (char *)&ra, as)) { |
| ra.sun_path[up] = '\0'; |
| if (ra.sun_path[0]) { |
| ras = 1; |
| if (Sfile && is_file_named(ra.sun_path, 0)) |
| Lf->sf = SELNM; |
| } |
| } |
| } |
| # endif /* UNIXWAREV<70103 */ |
| |
| /* |
| * Start Namech[] with the service type, converted to a name, ala netstat. |
| */ |
| switch (ss.servtype) { |
| case T_COTS: |
| case T_COTS_ORD: |
| ty = "stream"; |
| break; |
| case T_CLTS: |
| ty = "dgram"; |
| break; |
| default: |
| ty = (char *)NULL; |
| } |
| if (ty) { |
| (void) snpf(Namech, Namechl, "%s", ty); |
| ty = ":"; |
| } else { |
| Namech[0] = '\0'; |
| ty = ""; |
| } |
| /* |
| * Add names to Namech[]. |
| */ |
| |
| #if UNIXWAREV<70103 |
| if (la && la->sun_path[0]) { |
| ep = endnm(&sz); |
| (void) snpf(ep, sz, "%s%s", ty, la->sun_path); |
| } |
| #else /* UNIXWAREV>=70103 */ |
| if (las) { |
| ep = endnm(&sz); |
| (void) snpf(ep, sz, "%s%s", ty, la.sun_path); |
| } |
| #endif /* UNIXWAREV<70103 */ |
| |
| ep = endnm(&sz); |
| |
| #if UNIXWAREV<70103 |
| if (ra && ra->sun_path[0]) |
| (void) snpf(ep, sz, "->%s", ra->sun_path); |
| #else /* UNIXWAREV>=70103 */ |
| if (ras) |
| (void) snpf(ep, sz, "->%s", ra.sun_path); |
| #endif /* UNIXWAREV<70103 */ |
| |
| else if ((ka = (KA_T)ss.conn_ux)) |
| (void) snpf(ep, sz, "->%s", print_kptr(ka, (char *)NULL, 0)); |
| if (Namech[0]) |
| enter_nm(Namech); |
| return(1); |
| } |
| |
| |
| # if UNIXWAREV<70103 |
| /* |
| * find_unix_sockaddr_un() -- find UNIX socket address structure |
| * |
| */ |
| |
| static struct sockaddr_un * |
| find_unix_sockaddr_un(ka) |
| KA_T ka; /* socket's kernel address */ |
| { |
| static struct soreq *al = (struct soreq *)NULL; |
| static int alct = 0; |
| int i; |
| |
| if (!al) { |
| MALLOC_S alen, len; |
| char *ch = (char *)NULL; |
| int ct, pct; |
| struct strioctl ioc; |
| int sock = -1; |
| |
| if (alct < 0) |
| return((struct sockaddr_un *)NULL); |
| /* |
| * If there has been no attempt to acquire the address list yet, |
| * do so. |
| * |
| * Get a SOCK_STREAM PF_UNIX socket descriptor and use ioctl() to |
| * send a stream message to acquire the list of PF_UNIX addresses. |
| */ |
| if ((sock = socket (PF_UNIX, SOCK_STREAM, 0)) < 0) { |
| |
| /* |
| * Some error was detected. Return allocated resources and |
| * indicate that no further attempts need be made. |
| */ |
| |
| find_err_exit: |
| |
| alct = -1; |
| if (sock >= 0) |
| close(sock); |
| if (ch) |
| (void) free((FREE_P *)ch); |
| return((struct sockaddr_un *)NULL); |
| } |
| /* |
| * Read the address list. Before starting, get an estimate of its |
| * size and add a small safety margin. |
| */ |
| if ((ct = ioctl(sock, SI_UX_COUNT, 0)) < 0) |
| goto find_err_exit; |
| ct += 32; |
| pct = 0; |
| do { |
| if (ct > pct) { |
| |
| /* |
| * If the previously allocated space is insufficient, |
| * or if none has been allocated, allocate space. |
| */ |
| alen = (MALLOC_S)(ct * sizeof(struct soreq)); |
| if (ch) |
| ch = (char *)realloc((MALLOC_P *)ch, alen); |
| else |
| ch = (char *)malloc(alen); |
| if (!ch) |
| goto find_err_exit; |
| pct = ct; |
| } |
| /* |
| * Read the address list into the allocated space. |
| */ |
| ioc.ic_cmd = SI_UX_LIST; |
| ioc.ic_dp = ch; |
| ioc.ic_len = (int)alen; |
| ioc.ic_timout = 0; |
| if ((ct = ioctl(sock, I_STR, &ioc)) < 0) |
| goto find_err_exit; |
| } while (ct > pct); |
| /* |
| * The list has been acquired. Free any excess space pre-allocated to |
| * it, then save its address. Close the stream socket. |
| */ |
| alct = ct; |
| if ((len = (MALLOC_S)(alct * sizeof(struct soreq))) < alen) { |
| if (!(ch = (char *)realloc((MALLOC_P *)ch, len))) |
| goto find_err_exit; |
| } |
| al = (struct soreq *)ch; |
| close(sock); |
| } |
| /* |
| * Search a previously acquired address list, based on the supplied kernel |
| * socket address. If an entry is found, return a pointer to it, making |
| * sure the path it contains is terminated. |
| */ |
| for (i = 0; i < alct; i++) { |
| if ((KA_T)al[i].so_addr == ka) |
| break; |
| } |
| if (i >= alct || !al[i].sockaddr.sun_path[0]) |
| return((struct sockaddr_un *)NULL); |
| al[i].sockaddr.sun_path[(int)(sizeof(al[i].sockaddr.sun_path) - 1)] |
| = '\0'; |
| return(&al[i].sockaddr); |
| } |
| # endif /* UNIXWAREV<70103 */ |
| #endif /* UNIXWAREV>=70101 */ |