| /* |
| * dsock.c -- pstat-based HP-UX socket and stream processing functions for lsof |
| */ |
| |
| |
| /* |
| * Copyright 1999 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 1999 Purdue Research Foundation.\nAll rights reserved.\n"; |
| static char *rcsid = "$Id"; |
| #endif |
| |
| |
| #include "lsof.h" |
| |
| |
| /* |
| * Local function prototypes |
| */ |
| |
| #if defined(PS_STR_XPORT_DATA) |
| _PROTOTYPE(static void make_sock,(struct pst_fileinfo2 *f, |
| struct pst_stream *sh, |
| struct pst_socket *s)); |
| #endif /* defined(PS_STR_XPORT_DATA) */ |
| |
| _PROTOTYPE(static void printpsproto,(uint32_t p)); |
| |
| |
| /* |
| * Local macros |
| */ |
| |
| #if defined(HASIPv6) |
| |
| /* |
| * IPv6_2_IPv4() -- macro to define the address of an IPv4 address contained |
| * in an IPv6 address |
| */ |
| |
| #define IPv6_2_IPv4(v6) (((uint8_t *)((struct in6_addr *)v6)->s6_addr)+12) |
| #endif /* defined(HASIPv6) */ |
| |
| |
| /* |
| * build_IPstates() -- build the TCP and UDP state tables |
| */ |
| |
| void |
| build_IPstates() |
| { |
| if (!TcpSt) { |
| (void) enter_IPstate("TCP", "CLOSED", PS_TCPS_CLOSED); |
| (void) enter_IPstate("TCP", "IDLE", PS_TCPS_IDLE); |
| (void) enter_IPstate("TCP", "BOUND", PS_TCPS_BOUND); |
| (void) enter_IPstate("TCP", "LISTEN", PS_TCPS_LISTEN); |
| (void) enter_IPstate("TCP", "SYN_SENT", PS_TCPS_SYN_SENT); |
| (void) enter_IPstate("TCP", "SYN_RCVD", PS_TCPS_SYN_RCVD); |
| (void) enter_IPstate("TCP", "ESTABLISHED", PS_TCPS_ESTABLISHED); |
| (void) enter_IPstate("TCP", "CLOSE_WAIT", PS_TCPS_CLOSE_WAIT); |
| (void) enter_IPstate("TCP", "FIN_WAIT_1", PS_TCPS_FIN_WAIT_1); |
| (void) enter_IPstate("TCP", "CLOSING", PS_TCPS_CLOSING); |
| (void) enter_IPstate("TCP", "LAST_ACK", PS_TCPS_LAST_ACK); |
| (void) enter_IPstate("TCP", "FIN_WAIT_2", PS_TCPS_FIN_WAIT_2); |
| (void) enter_IPstate("TCP", "TIME_WAIT", PS_TCPS_TIME_WAIT); |
| (void) enter_IPstate("TCP", (char *)NULL, 0); |
| } |
| if (!UdpSt) { |
| (void) enter_IPstate("UDP", "Uninitialized", PS_TS_UNINIT); |
| (void) enter_IPstate("UDP", "Unbound", PS_TS_UNBND); |
| (void) enter_IPstate("UDP", "Wait_BIND_REQ_Ack", PS_TS_WACK_BREQ); |
| (void) enter_IPstate("UDP", "Wait_UNBIND_REQ_Ack", PS_TS_WACK_UREQ); |
| (void) enter_IPstate("UDP", "Idle", PS_TS_IDLE); |
| (void) enter_IPstate("UDP", "Wait_OPT_REQ_Ack", PS_TS_WACK_OPTREQ); |
| (void) enter_IPstate("UDP", "Wait_CONN_REQ_Ack", PS_TS_WACK_CREQ); |
| (void) enter_IPstate("UDP", "Wait_CONN_REQ_Confirm", |
| PS_TS_WCON_CREQ); |
| (void) enter_IPstate("UDP", "Wait_CONN_IND_Response", |
| PS_TS_WRES_CIND); |
| (void) enter_IPstate("UDP", "Wait_CONN_RES_Ack", PS_TS_WACK_CRES); |
| (void) enter_IPstate("UDP", "Wait_Data_Xfr", PS_TS_DATA_XFER); |
| (void) enter_IPstate("UDP", "Wait_Read_Release", PS_TS_WIND_ORDREL); |
| (void) enter_IPstate("UDP", "Wait_Write_Release", |
| PS_TS_WREQ_ORDREL); |
| (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", |
| PS_TS_WACK_DREQ6); |
| (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", |
| PS_TS_WACK_DREQ7); |
| (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", |
| PS_TS_WACK_DREQ9); |
| (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", |
| PS_TS_WACK_DREQ10); |
| (void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", |
| PS_TS_WACK_DREQ11); |
| (void) enter_IPstate("UDP", "Internal", PS_TS_WACK_ORDREL); |
| (void) enter_IPstate("UDP", (char *)NULL, 0); |
| } |
| } |
| |
| |
| #if defined(PS_STR_XPORT_DATA) |
| /* |
| * make_sock() -- make a socket from the eXPORT data in a stream's head |
| */ |
| |
| static void |
| make_sock(f, sh, s) |
| struct pst_fileinfo2 *f; /* pst_fileinfo2 */ |
| struct pst_stream *sh; /* stream head */ |
| struct pst_socket *s; /* constructed socket */ |
| { |
| size_t sz; |
| /* |
| * Zero the destination pst_socket structure and propagate its file and node |
| * IDs from the stream head. Also propagate the linger time. |
| */ |
| (void)memset((void *)s, 0, sizeof(struct pst_socket)); |
| s->pst_hi_fileid = sh->val.head.pst_hi_fileid; |
| s->pst_lo_fileid = sh->val.head.pst_lo_fileid; |
| s->pst_hi_nodeid = sh->val.head.pst_hi_nodeid; |
| s->pst_lo_nodeid = sh->val.head.pst_lo_nodeid; |
| s->pst_linger = sh->pst_str_xport_linger; |
| /* |
| * Convert stream family to socket family and stream protocol to socket |
| * protocol. |
| * |
| * This could be avoided if PSTAT were to use a common set of family and |
| * protocol symbols. |
| */ |
| switch (sh->pst_str_xport_family) { |
| case PS_STR_XPORT_AFINET: |
| s->pst_family = PS_AF_INET; |
| break; |
| case PS_STR_XPORT_AFINET6: |
| s->pst_family = PS_AF_INET6; |
| break; |
| default: |
| s->pst_family = sh->pst_str_xport_family; |
| } |
| switch (sh->pst_str_xport_protocol) { |
| case PS_STR_XPORT_TCP_PROTO: |
| s->pst_protocol = PS_PROTO_TCP; |
| break; |
| case PS_STR_XPORT_UDP_PROTO: |
| s->pst_protocol = PS_PROTO_UDP; |
| break; |
| default: |
| s->pst_protocol = sh->pst_str_xport_protocol; |
| } |
| /* |
| * Copy stream size information. |
| */ |
| s->pst_qlimit = sh->pst_str_xport_qlimit; |
| s->pst_qlen = sh->pst_str_xport_qlen; |
| s->pst_idata = sh->pst_str_xport_idata; |
| s->pst_ibufsz = sh->pst_str_xport_ibufsz; |
| s->pst_rwnd = sh->pst_str_xport_rwnd; |
| s->pst_swnd = sh->pst_str_xport_swnd; |
| s->pst_odata = sh->pst_str_xport_odata; |
| s->pst_obufsz = sh->pst_str_xport_obufsz; |
| /* |
| * Propagate protocol state from stream symbol values to socket ones. |
| * |
| * This could be avoided if PSTAT were to use a common set of protocol |
| * state symbols. |
| */ |
| if (s->pst_protocol == PS_PROTO_TCP) { |
| switch (sh->pst_str_xport_pstate) { |
| |
| #if defined(PS_STR_XPORT_TCPS_CLOSED) && defined(PS_TCPS_CLOSED) \ |
| && (PS_STR_XPORT_TCPS_CLOSED != PS_TCPS_CLOSED) |
| case PS_STR_XPORT_TCPS_CLOSED: |
| s->pst_pstate = PS_TCPS_CLOSED; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TCPS_IDLE) && defined(PS_TCPS_IDLE) \ |
| && (PS_STR_XPORT_TCPS_IDLE != PS_TCPS_IDLE) |
| case PS_STR_XPORT_TCPS_IDLE: |
| s->pst_pstate = PS_TCPS_IDLE; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TCPS_BOUND) && defined(PS_TCPS_BOUND) \ |
| && (PS_STR_XPORT_TCPS_BOUND != PS_TCPS_BOUND) |
| case PS_STR_XPORT_TCPS_BOUND: |
| s->pst_pstate = PS_TCPS_BOUND; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TCPS_LISTEN) && defined(PS_TCPS_LISTEN) \ |
| && (PS_STR_XPORT_TCPS_LISTEN != PS_TCPS_LISTEN) |
| case PS_STR_XPORT_TCPS_LISTEN: |
| s->pst_pstate = PS_TCPS_LISTEN; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TCPS_SYN_SENT) && defined(PS_TCPS_SYN_SENT) \ |
| && (PS_STR_XPORT_TCPS_SYN_SENT != PS_TCPS_SYN_SENT) |
| case PS_STR_XPORT_TCPS_SYN_SENT: |
| s->pst_pstate = PS_TCPS_SYN_SENT; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TCPS_SYN_RCVD) && defined(PS_TCPS_SYN_RCVD) \ |
| && (PS_STR_XPORT_TCPS_SYN_RCVD != PS_TCPS_SYN_RCVD) |
| case PS_STR_XPORT_TCPS_SYN_RCVD: |
| s->pst_pstate = PS_TCPS_SYN_RCVD; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TCPS_ESTABLISHED) && defined(PS_TCPS_ESTABLISHED) \ |
| && (PS_STR_XPORT_TCPS_ESTABLISHED != PS_TCPS_ESTABLISHED) |
| case PS_STR_XPORT_TCPS_ESTABLISHED: |
| s->pst_pstate = PS_TCPS_ESTABLISHED; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TCPS_CLOSE_WAIT) && defined(PS_TCPS_CLOSE_WAIT) \ |
| && (PS_STR_XPORT_TCPS_CLOSE_WAIT != PS_TCPS_CLOSE_WAIT) |
| case PS_STR_XPORT_TCPS_CLOSE_WAIT: |
| s->pst_pstate = PS_TCPS_CLOSE_WAIT; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TCPS_FIN_WAIT_1) && defined(PS_TCPS_FIN_WAIT_1) \ |
| && (PS_STR_XPORT_TCPS_FIN_WAIT_1 != PS_TCPS_FIN_WAIT_1) |
| case PS_STR_XPORT_TCPS_FIN_WAIT_1: |
| s->pst_pstate = PS_TCPS_FIN_WAIT_1; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TCPS_CLOSING) && defined(PS_TCPS_CLOSING) \ |
| && (PS_STR_XPORT_TCPS_CLOSING != PS_TCPS_CLOSING) |
| case PS_STR_XPORT_TCPS_CLOSING: |
| s->pst_pstate = PS_TCPS_CLOSING; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TCPS_LAST_ACK) && defined(PS_TCPS_LAST_ACK) \ |
| && (PS_STR_XPORT_TCPS_LAST_ACK != PS_TCPS_LAST_ACK) |
| case PS_STR_XPORT_TCPS_LAST_ACK: |
| s->pst_pstate = PS_TCPS_LAST_ACK; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TCPS_FIN_WAIT_2) && defined(PS_TCPS_FIN_WAIT_2) \ |
| && (PS_STR_XPORT_TCPS_FIN_WAIT_2 != PS_TCPS_FIN_WAIT_2) |
| case PS_STR_XPORT_TCPS_FIN_WAIT_2: |
| s->pst_pstate = PS_TCPS_FIN_WAIT_2; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TCPS_TIME_WAIT) && defined(PS_TCPS_TIME_WAIT) \ |
| && (PS_STR_XPORT_TCPS_TIME_WAIT != PS_TCPS_TIME_WAIT) |
| case PS_STR_XPORT_TCPS_TIME_WAIT: |
| s->pst_pstate = PS_TCPS_TIME_WAIT; |
| break; |
| #endif |
| |
| default: |
| s->pst_pstate = sh->pst_str_xport_pstate; |
| } |
| } else if (s->pst_protocol == PS_PROTO_UDP) { |
| switch (sh->pst_str_xport_pstate) { |
| |
| #if defined(PS_STR_XPORT_TS_UNINIT) && defined(PS_TS_UNINIT) \ |
| && (PS_STR_XPORT_TS_UNINIT != PS_TS_UNINIT) |
| case PS_STR_XPORT_TS_UNINIT: |
| s->pst_pstate = PS_TS_UNINIT; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TS_UNBND) && defined(PS_TS_UNBND) \ |
| && (PS_STR_XPORT_TS_UNBND != PS_TS_UNBND) |
| case PS_STR_XPORT_TS_UNBND: |
| s->pst_pstate = PS_TS_UNBND; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TS_WACK_BREQ) && defined(PS_TS_WACK_BREQ) \ |
| && (PS_STR_XPORT_TS_WACK_BREQ != PS_TS_WACK_BREQ) |
| case PS_STR_XPORT_TS_WACK_BREQ: |
| s->pst_pstate = PS_TS_WACK_BREQ; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TS_WACK_UREQ) && defined(PS_TS_WACK_UREQ) \ |
| && (PS_STR_XPORT_TS_WACK_UREQ != PS_TS_WACK_UREQ) |
| case PS_STR_XPORT_TS_WACK_UREQ: |
| s->pst_pstate = PS_TS_WACK_UREQ; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TS_IDLE) && defined(PS_TS_IDLE) \ |
| && (PS_STR_XPORT_TS_IDLE != PS_TS_IDLE) |
| case PS_STR_XPORT_TS_IDLE: |
| s->pst_pstate = PS_TS_IDLE; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TS_WACK_OPTREQ) && defined(PS_TS_WACK_OPTREQ) \ |
| && (PS_STR_XPORT_TS_WACK_OPTREQ != PS_TS_WACK_OPTREQ) |
| case PS_STR_XPORT_TS_WACK_OPTREQ: |
| s->pst_pstate = PS_TS_WACK_OPTREQ; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TS_WACK_CREQ) && defined(PS_TS_WACK_CREQ) \ |
| && (PS_STR_XPORT_TS_WACK_CREQ != PS_TS_WACK_CREQ) |
| case PS_STR_XPORT_TS_WACK_CREQ: |
| s->pst_pstate = PS_TS_WACK_CREQ; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TS_WCON_CREQ) && defined(PS_TS_WCON_CREQ) \ |
| && (PS_STR_XPORT_TS_WCON_CREQ != PS_TS_WCON_CREQ) |
| case PS_STR_XPORT_TS_WCON_CREQ: |
| s->pst_pstate = PS_TS_WCON_CREQ; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TS_WRES_CIND) && defined(PS_TS_WRES_CIND) \ |
| && (PS_STR_XPORT_TS_WRES_CIND != PS_TS_WRES_CIND) |
| case PS_STR_XPORT_TS_WRES_CIND: |
| s->pst_pstate = PS_TS_WRES_CIND; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TS_WACK_CRES) && defined(PS_TS_WACK_CRES) \ |
| && (PS_STR_XPORT_TS_WACK_CRES != PS_TS_WACK_CRES) |
| case PS_STR_XPORT_TS_WACK_CRES: |
| s->pst_pstate = PS_TS_WACK_CRES; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TS_DATA_XFER) && defined(PS_TS_DATA_XFER) \ |
| && (PS_STR_XPORT_TS_DATA_XFER != PS_TS_DATA_XFER) |
| case PS_STR_XPORT_TS_DATA_XFER: |
| s->pst_pstate = PS_TS_DATA_XFER; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TS_WIND_ORDREL) && defined(PS_TS_WIND_ORDREL) \ |
| && (PS_STR_XPORT_TS_WIND_ORDREL != PS_TS_WIND_ORDREL) |
| case PS_STR_XPORT_TS_WIND_ORDREL: |
| s->pst_pstate = PS_TS_WIND_ORDREL; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TS_WREQ_ORDREL) && defined(PS_TS_WREQ_ORDREL) \ |
| && (PS_STR_XPORT_TS_WREQ_ORDREL != PS_TS_WREQ_ORDREL) |
| case PS_STR_XPORT_TS_WREQ_ORDREL: |
| s->pst_pstate = PS_TS_WREQ_ORDREL; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TS_WACK_DREQ6) && defined(PS_TS_WACK_DREQ6) \ |
| && (PS_STR_XPORT_TS_WACK_DREQ6 != PS_TS_WACK_DREQ6) |
| case PS_STR_XPORT_TS_WACK_DREQ6: |
| s->pst_pstate = PS_TS_WACK_DREQ6; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TS_WACK_DREQ7) && defined(PS_TS_WACK_DREQ7) \ |
| && (PS_STR_XPORT_TS_WACK_DREQ7 != PS_TS_WACK_DREQ7) |
| case PS_STR_XPORT_TS_WACK_DREQ7: |
| s->pst_pstate = PS_TS_WACK_DREQ7; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TS_WACK_DREQ9) && defined(PS_TS_WACK_DREQ9) \ |
| && (PS_STR_XPORT_TS_WACK_DREQ9 != PS_TS_WACK_DREQ9) |
| case PS_STR_XPORT_TS_WACK_DREQ9: |
| s->pst_pstate = PS_TS_WACK_DREQ9; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TS_WACK_DREQ10) && defined(PS_TS_WACK_DREQ10) \ |
| && (PS_STR_XPORT_TS_WACK_DREQ10 != PS_TS_WACK_DREQ10) |
| case PS_STR_XPORT_TS_WACK_DREQ10: |
| s->pst_pstate = PS_TS_WACK_DREQ10; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TS_WACK_DREQ11) && defined(PS_TS_WACK_DREQ11) \ |
| && (PS_STR_XPORT_TS_WACK_DREQ11 != PS_TS_WACK_DREQ11) |
| case PS_STR_XPORT_TS_WACK_DREQ11: |
| s->pst_pstate = PS_TS_WACK_DREQ11; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TS_WACK_ORDREL) && defined(PS_TS_WACK_ORDREL) \ |
| && (PS_STR_XPORT_TS_WACK_ORDREL != PS_TS_WACK_ORDREL) |
| case PS_STR_XPORT_TS_WACK_ORDREL: |
| s->pst_pstate = PS_TS_WACK_ORDREL; |
| break; |
| #endif |
| |
| #if defined(PS_STR_XPORT_TS_NOSTATES) && defined(PS_TS_NOSTATES) \ |
| && (PS_STR_XPORT_TS_NOSTATES != PS_TS_NOSTATES) |
| case PS_STR_XPORT_TS_NOSTATES: |
| s->pst_pstate = PS_TS_NOSTATES; |
| break; |
| #endif |
| |
| default: |
| s->pst_pstate = sh->pst_str_xport_pstate; |
| } |
| } else |
| s->pst_pstate = sh->pst_str_xport_pstate; |
| /* |
| * Now propagate the bound and remote address information from pst_stream |
| * to the pst_socket structure. Validate the copy lengths. |
| */ |
| sz = (size_t)sh->pst_str_xport_boundaddr_len; |
| if (sz > sizeof(s->pst_boundaddr)) |
| sz = sizeof(s->pst_boundaddr); |
| if ((s->pst_boundaddr_len = sz)) { |
| (void) memcpy((void *)s->pst_boundaddr, |
| (const void *)sh->pst_str_xport_boundaddr, sz); |
| } |
| sz = (size_t)sh->pst_str_xport_remaddr_len; |
| if (sz > sizeof(s->pst_remaddr)) |
| sz = sizeof(s->pst_remaddr); |
| if ((s->pst_remaddr_len = sz)) { |
| (void) memcpy((void *)s->pst_remaddr, |
| (const void *)sh->pst_str_xport_remaddr, sz); |
| } |
| } |
| #endif /* defined(PS_STR_XPORT_DATA) */ |
| |
| |
| /* |
| * printpsproto() -- print PSTAT protocol name |
| */ |
| |
| static void |
| printpsproto(p) |
| uint32_t p; /* protocol number */ |
| { |
| int i; |
| static int m = -1; |
| char *s; |
| |
| switch (p) { |
| case PS_PROTO_IP: |
| s = "IP"; |
| break; |
| case PS_PROTO_ICMP: |
| s = "ICMP"; |
| break; |
| case PS_PROTO_IGMP: |
| s = "IGMP"; |
| break; |
| case PS_PROTO_GGP: |
| s = "GGP"; |
| break; |
| case PS_PROTO_IPIP: |
| s = "IPIP"; |
| break; |
| case PS_PROTO_TCP: |
| s = "TCP"; |
| break; |
| case PS_PROTO_EGP: |
| s = "EGP"; |
| break; |
| case PS_PROTO_IGP: |
| s = "IGP"; |
| break; |
| case PS_PROTO_PUP: |
| s = "PUP"; |
| break; |
| case PS_PROTO_UDP: |
| s = "UDP"; |
| break; |
| case PS_PROTO_IDP: |
| s = "IDP"; |
| break; |
| case PS_PROTO_XTP: |
| s = "XTP"; |
| break; |
| case PS_PROTO_ESP: |
| s = "ESP"; |
| break; |
| case PS_PROTO_AH: |
| s = "AH"; |
| break; |
| case PS_PROTO_OSPF: |
| s = "OSPF"; |
| break; |
| case PS_PROTO_IPENCAP: |
| s = "IPENCAP"; |
| break; |
| case PS_PROTO_ENCAP: |
| s = "ENCAP"; |
| break; |
| case PS_PROTO_PXP: |
| s = "PXP"; |
| break; |
| case PS_PROTO_RAW: |
| s = "RAW"; |
| break; |
| default: |
| s = (char *)NULL; |
| } |
| if (s) |
| (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL-1, s); |
| else { |
| if (m < 0) { |
| for (i = 0, m = 1; i < IPROTOL-2; i++) |
| m *= 10; |
| } |
| if (m > p) |
| (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%d?", p); |
| else |
| (void) snpf(Lf->iproto, sizeof(Lf->iproto), "*%d?", |
| p % (m/10)); |
| } |
| } |
| |
| |
| /* |
| * print_tcptpi() -- print TCP/TPI info |
| */ |
| |
| void |
| print_tcptpi(nl) |
| int nl; /* 1 == '\n' required */ |
| { |
| char *cp = (char *)NULL; |
| char sbuf[128]; |
| int i; |
| int ps = 0; |
| unsigned int u; |
| |
| if (Ftcptpi & TCPTPI_STATE) { |
| switch (Lf->lts.type) { |
| case 0: /* TCP */ |
| if (!TcpSt) |
| (void) build_IPstates(); |
| if ((i = Lf->lts.state.i + TcpStOff) < 0 || i >= TcpNstates) { |
| (void) snpf(sbuf, sizeof(sbuf), "UknownState_%d", |
| Lf->lts.state.i); |
| cp = sbuf; |
| } else |
| cp = TcpSt[i]; |
| break; |
| case 1: /* UDP */ |
| if (!UdpSt) |
| (void) build_IPstates(); |
| if ((u = Lf->lts.state.ui + UdpStOff) > UdpNstates) { |
| (void) snpf(sbuf, sizeof(sbuf), "UNKNOWN_TPI_STATE_%u", |
| Lf->lts.state.ui); |
| cp = sbuf; |
| } else |
| cp = UdpSt[u]; |
| } |
| 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.qlens || Lf->lts.qlims) { |
| char sep = ' '; |
| |
| if (Ffield) |
| sep = LSOF_FID_TCPTPI; |
| else if (!ps) |
| sep = '('; |
| (void) printf("%cSO", sep); |
| ps++; |
| sep = '='; |
| |
| # if defined(PS_SO_ACCEPTCONN) |
| if (opt & PS_SO_ACCEPTCONN) { |
| (void) printf("%cACCEPTCONN", sep); |
| opt &= ~PS_SO_ACCEPTCONN; |
| sep = ','; |
| } |
| # endif /* defined(PS_SO_ACCEPTCONN) */ |
| |
| # if defined(PS_SO_BROADCAST) |
| if (opt & PS_SO_BROADCAST) { |
| (void) printf("%cBROADCAST", sep); |
| opt &= ~PS_SO_BROADCAST; |
| sep = ','; |
| } |
| # endif /* defined(PS_SO_BROADCAST) */ |
| |
| # if defined(PS_SO_DEBUG) |
| if (opt & PS_SO_DEBUG) { |
| (void) printf("%cDEBUG", sep); |
| opt &= ~PS_SO_DEBUG; |
| sep = ','; |
| } |
| # endif /* defined(PS_SO_DEBUG) */ |
| |
| # if defined(PS_SO_DONTROUTE) |
| if (opt & PS_SO_DONTROUTE) { |
| (void) printf("%cDONTROUTE", sep); |
| opt &= ~PS_SO_DONTROUTE; |
| sep = ','; |
| } |
| # endif /* defined(PS_SO_DONTROUTE) */ |
| |
| # if defined(PS_SO_GETIFADDR) |
| if (opt & PS_SO_GETIFADDR) { |
| (void) printf("%cGETIFADDR", sep); |
| opt &= ~PS_SO_GETIFADDR; |
| sep = ','; |
| } |
| # endif /* defined(PS_SO_GETIFADDR) */ |
| |
| # if defined(PS_SO_INPCB_COPY) |
| if (opt & PS_SO_INPCB_COPY) { |
| (void) printf("%cINPCB_COPY", sep); |
| opt &= ~PS_SO_INPCB_COPY; |
| sep = ','; |
| } |
| # endif /* defined(PS_SO_INPCB_COPY) */ |
| |
| # if defined(PS_SO_KEEPALIVE) |
| if (opt & PS_SO_KEEPALIVE) { |
| (void) printf("%cKEEPALIVE", sep); |
| if (Lf->lts.kai) |
| (void) printf("=%d", Lf->lts.kai); |
| opt &= ~PS_SO_KEEPALIVE; |
| sep = ','; |
| } |
| # endif /* defined(PS_SO_KEEPALIVE) */ |
| |
| # if defined(PS_SO_LINGER) |
| if (opt & PS_SO_LINGER) { |
| (void) printf("%cLINGER", sep); |
| if (Lf->lts.ltm) |
| (void) printf("=%d", Lf->lts.ltm); |
| opt &= ~PS_SO_LINGER; |
| sep = ','; |
| } |
| # endif /* defined(PS_SO_LINGER) */ |
| |
| # if defined(PS_SO_OOBINLINE) |
| if (opt & PS_SO_OOBINLINE) { |
| (void) printf("%cOOBINLINE", sep); |
| opt &= ~PS_SO_OOBINLINE; |
| sep = ','; |
| } |
| # endif /* defined(PS_SO_OOBINLINE) */ |
| |
| # if defined(PS_SO_PMTU) |
| if (opt & PS_SO_PMTU) { |
| (void) printf("%cPMTU", sep); |
| opt &= ~PS_SO_PMTU; |
| sep = ','; |
| } |
| # endif /* defined(PS_SO_PMTU) */ |
| |
| 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 defined(PS_SO_REUSEADDR) |
| if (opt & PS_SO_REUSEADDR) { |
| (void) printf("%cREUSEADDR", sep); |
| opt &= ~PS_SO_REUSEADDR; |
| sep = ','; |
| } |
| # endif /* defined(PS_SO_REUSEADDR) */ |
| |
| # if defined(PS_SO_REUSEPORT) |
| if (opt & PS_SO_REUSEPORT) { |
| (void) printf("%cREUSEPORT", sep); |
| opt &= ~PS_SO_REUSEPORT; |
| sep = ','; |
| } |
| # endif /* defined(PS_SO_REUSEPORT) */ |
| |
| # if defined(PS_SO_USELOOPBACK) |
| if (opt & PS_SO_USELOOPBACK) { |
| (void) printf("%cUSELOOPBACK", sep); |
| opt &= ~PS_SO_USELOOPBACK; |
| sep = ','; |
| } |
| # endif /* defined(PS_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(PS_SS_ASYNC) |
| if (ss & PS_SS_ASYNC) { |
| (void) printf("%cASYNC", sep); |
| ss &= ~PS_SS_ASYNC; |
| sep = ','; |
| } |
| # endif /* defined(PS_SS_ASYNC) */ |
| |
| # if defined(PS_SS_BOUND) |
| if (ss & PS_SS_BOUND) { |
| (void) printf("%cBOUND", sep); |
| ss &= ~PS_SS_BOUND; |
| sep = ','; |
| } |
| # endif /* defined(PS_SS_BOUND) */ |
| |
| # if defined(PS_SS_CANTRCVMORE) |
| if (ss & PS_SS_CANTRCVMORE) { |
| (void) printf("%cCANTRCVMORE", sep); |
| ss &= ~PS_SS_CANTRCVMORE; |
| sep = ','; |
| } |
| # endif /* defined(PS_SS_CANTRCVMORE) */ |
| |
| # if defined(PS_SS_CANTSENDMORE) |
| if (ss & PS_SS_CANTSENDMORE) { |
| (void) printf("%cCANTSENDMORE", sep); |
| ss &= ~PS_SS_CANTSENDMORE; |
| sep = ','; |
| } |
| # endif /* defined(PS_SS_CANTSENDMORE) */ |
| |
| # if defined(PS_SS_ISCONNECTED) |
| if (ss & PS_SS_ISCONNECTED) { |
| (void) printf("%cISCONNECTED", sep); |
| ss &= ~PS_SS_ISCONNECTED; |
| sep = ','; |
| } |
| # endif /* defined(PS_SS_ISCONNECTED) */ |
| |
| # if defined(PS_SS_ISCONNECTING) |
| if (ss & PS_SS_ISCONNECTING) { |
| (void) printf("%cISCONNECTING", sep); |
| ss &= ~PS_SS_ISCONNECTING; |
| sep = ','; |
| } |
| # endif /* defined(PS_SS_ISCONNECTING) */ |
| |
| # if defined(PS_SS_ISDISCONNECTI) |
| if (ss & PS_SS_ISDISCONNECTI) { |
| (void) printf("%cISDISCONNECTI", sep); |
| ss &= ~PS_SS_ISDISCONNECTI; |
| sep = ','; |
| } |
| # endif /* defined(PS_SS_ISDISCONNECTI) */ |
| |
| # if defined(PS_SS_INTERRUPTED) |
| if (ss & PS_SS_INTERRUPTED) { |
| (void) printf("%cINTERRUPTED", sep); |
| ss &= ~PS_SS_INTERRUPTED; |
| sep = ','; |
| } |
| # endif /* defined(PS_SS_INTERRUPTED) */ |
| |
| # if defined(PS_SS_NBIO) |
| if (ss & PS_SS_NBIO) { |
| (void) printf("%cNBIO", sep); |
| ss &= ~PS_SS_NBIO; |
| sep = ','; |
| } |
| # endif /* defined(PS_SS_NBIO) */ |
| |
| # if defined(PS_SS_NOFDREF) |
| if (ss & PS_SS_NOFDREF) { |
| (void) printf("%cNOFDREF", sep); |
| ss &= ~PS_SS_NOFDREF; |
| sep = ','; |
| } |
| # endif /* defined(PS_SS_NOFDREF) */ |
| |
| # if defined(PS_SS_NOUSER) |
| if (ss & PS_SS_NOUSER) { |
| (void) printf("%cNOUSER", sep); |
| ss &= ~PS_SS_NOUSER; |
| sep = ','; |
| } |
| # endif /* defined(PS_SS_NOUSER) */ |
| |
| # if defined(PS_SS_NOWAIT) |
| if (ss & PS_SS_NOWAIT) { |
| (void) printf("%cNOWAIT", sep); |
| ss &= ~PS_SS_NOWAIT; |
| sep = ','; |
| } |
| # endif /* defined(PS_SS_NOWAIT) */ |
| |
| # if defined(PS_SS_PRIV) |
| if (ss & PS_SS_PRIV) { |
| (void) printf("%cPRIV", sep); |
| ss &= ~PS_SS_PRIV; |
| sep = ','; |
| } |
| # endif /* defined(PS_SS_PRIV) */ |
| |
| # if defined(PS_SS_RCVATMARK) |
| if (ss & PS_SS_RCVATMARK) { |
| (void) printf("%cRCVATMARK", sep); |
| ss &= ~PS_SS_RCVATMARK; |
| sep = ','; |
| } |
| # endif /* defined(PS_SS_RCVATMARK) */ |
| |
| # if defined(PS_SS_XOPEN_EXT1) |
| if (ss & PS_SS_XOPEN_EXT1) { |
| (void) printf("%cXOPEN_EXT1", sep); |
| ss &= ~PS_SS_XOPEN_EXT1; |
| sep = ','; |
| } |
| # endif /* defined(PS_SS_XOPEN_EXT1) */ |
| |
| if (ss) |
| (void) printf("%cUNKNOWN=%#x", sep, ss); |
| if (Ffield) |
| putchar(Terminator); |
| } |
| } |
| #endif /* defined(HASSOSTATE) */ |
| |
| #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 (Ftcptpi && !Ffield && ps) |
| putchar(')'); |
| if (nl) |
| putchar('\n'); |
| } |
| |
| |
| /* |
| * process_socket() -- process socket |
| */ |
| |
| void |
| process_socket(f, s) |
| struct pst_fileinfo2 *f; /* file information */ |
| struct pst_socket *s; /* optional socket information |
| * NULL == none */ |
| { |
| int af, err, fp, lp, tx; |
| char buf[1024], tbuf[32]; |
| unsigned char *fa = (unsigned char *)NULL; |
| unsigned char *la = (unsigned char *)NULL; |
| size_t len; |
| KA_T na, nau; |
| char *nma = (char *)NULL; |
| struct pst_filedetails pd; |
| struct sockaddr_in *sa; |
| int sx; |
| |
| #if defined(HASIPv6) |
| struct sockaddr_in6 *sa6; |
| #endif /* defined(HASIPv6) */ |
| |
| struct sockaddr_un *ua; |
| /* |
| * Read socket info, as required, so that the protocol state names can be |
| * tested as soon as possible. |
| */ |
| if (!s) { |
| if (!(s = read_sock(f))) { |
| (void) snpf(Namech, Namechl, |
| "can't read pst_socket%s%s", errno ? ": " : "", |
| errno ? strerror(errno) : ""); |
| (void) enter_nm(Namech); |
| return; |
| } |
| } |
| /* |
| * Collect protocol details so the protocol state name might be tested, |
| * as requested by options. |
| */ |
| switch (s->pst_family) { |
| case PS_AF_INET: |
| af = 4; |
| break; |
| |
| #if defined(HASIPv6) |
| case PS_AF_INET6: |
| af = 6; |
| break; |
| #endif /* defined(HASIPv6) */ |
| |
| default: |
| af = -1; |
| } |
| switch (s->pst_protocol) { |
| case PS_PROTO_TCP: |
| sx = (int)s->pst_pstate + TcpStOff; |
| tx = 0; |
| break; |
| case PS_PROTO_UDP: |
| sx = (unsigned int)s->pst_pstate + UdpStOff; |
| tx = 1; |
| break; |
| default: |
| sx = tx = -1; |
| } |
| /* |
| * Test the protocol state and name, setting the SELNET flag where possible. |
| */ |
| switch (tx) { |
| case 0: /* TCP */ |
| if (TcpStXn) { |
| |
| /* |
| * Check for TCP state exclusion. |
| */ |
| if (sx >= 0 && sx < TcpNstates) { |
| if (TcpStX[sx]) { |
| Lf->sf |= SELEXCLF; |
| return; |
| } |
| } |
| } |
| if (TcpStIn) { |
| if (sx >= 0 && sx < TcpNstates) { |
| if (TcpStI[sx]) |
| TcpStI[sx] = 2; |
| else { |
| Lf->sf |= SELEXCLF; |
| return; |
| } |
| } |
| } |
| break; |
| case 1: /* UDP */ |
| if (UdpStXn) { |
| |
| /* |
| * Check for UDP state exclusion. |
| */ |
| if (sx >= 0 && sx < UdpNstates) { |
| if (UdpStX[sx]) { |
| Lf->sf |= SELEXCLF; |
| return; |
| } |
| } |
| } |
| if (UdpStIn) { |
| if (sx >= 0 && sx < UdpNstates) { |
| if (UdpStI[sx]) |
| UdpStI[sx] = 2; |
| else { |
| Lf->sf |= SELEXCLF; |
| return; |
| } |
| } |
| } |
| break; |
| } |
| /* |
| * Set default type. |
| */ |
| (void) snpf(Lf->type, sizeof(Lf->type), "sock"); |
| Lf->inp_ty = 2; |
| /* |
| * Generate and save node ID. |
| */ |
| na = (KA_T)(((KA_T)(f->psf_hi_nodeid & 0xffffffff) << 32) |
| | (KA_T)(f->psf_lo_nodeid & 0xffffffff)); |
| |
| #if defined(HASFSTRUCT) |
| if (na && (Fsv & FSV_NI)) { |
| if (na) { |
| Lf->fna = na; |
| Lf->fsv |= FSV_NI; |
| } |
| } |
| #endif /* defined(HASFSTRUCT) */ |
| |
| /* |
| * Save size information, as requested. |
| */ |
| if (Fsize) { |
| if (Lf->access == 'r') |
| Lf->sz = (SZOFFTYPE)s->pst_idata; |
| else if (Lf->access == 'w') |
| Lf->sz = (SZOFFTYPE)s->pst_odata; |
| else |
| Lf->sz = (SZOFFTYPE)(s->pst_idata + s->pst_odata); |
| Lf->sz_def = 1; |
| } else |
| Lf->off_def = 1; |
| |
| #if defined(HASTCPTPIQ) |
| /* |
| * Enter queue sizes. |
| */ |
| switch (s->pst_family) { |
| case PS_AF_INET: |
| case PS_AF_INET6: |
| Lf->lts.rq = (unsigned long)s->pst_idata; |
| Lf->lts.sq = (unsigned long)s->pst_odata; |
| Lf->lts.rqs = Lf->lts.sqs = (unsigned char)1; |
| } |
| #endif /* defined(HASTCPTPIQ) */ |
| |
| #if defined(HASSOOPT) |
| /* |
| * Enter socket options. |
| */ |
| Lf->lts.opt = (unsigned int)s->pst_options; |
| Lf->lts.ltm = (unsigned int)s->pst_linger; |
| Lf->lts.qlen = (unsigned int)s->pst_qlen; |
| Lf->lts.qlim = (unsigned int)s->pst_qlimit; |
| Lf->lts.qlens = Lf->lts.qlims = (unsigned char)1; |
| #endif /* defined(HASSOOPT) */ |
| |
| #if defined(HASSOSTATE) |
| /* |
| * Enter socket state flags. |
| */ |
| Lf->lts.ss = (unsigned int)s->pst_state; |
| #endif /* defined(HASSOSTATE) */ |
| |
| #if defined(HASTCPTPIW) |
| /* |
| * Enter window sizes. |
| */ |
| switch (s->pst_family) { |
| case PS_AF_INET: |
| case PS_AF_INET6: |
| Lf->lts.rw = (unsigned long)s->pst_rwnd; |
| Lf->lts.ww = (unsigned long)s->pst_swnd; |
| Lf->lts.rws = Lf->lts.wws = (unsigned char)1; |
| } |
| #endif /* defined(HASTCPTPIW) */ |
| |
| /* |
| * Process socket by the associated domain family. |
| */ |
| switch (s->pst_family) { |
| case PS_AF_INET: |
| if (Fnet && (!FnetTy || (FnetTy != 6))) |
| Lf->sf |= SELNET; |
| (void) snpf(Lf->type, sizeof(Lf->type), |
| |
| #if defined(HASIPv6) |
| "IPv4" |
| #else /* !defined(HASIPv6) */ |
| "inet" |
| #endif /* defined(HASIPv6) */ |
| |
| ); |
| printpsproto(s->pst_protocol); |
| enter_dev_ch(print_kptr(na, (char *)NULL, 0)); |
| switch (s->pst_protocol) { |
| case PS_PROTO_TCP: |
| Lf->lts.type = 0; |
| Lf->lts.state.i = (int)s->pst_pstate; |
| break; |
| case PS_PROTO_UDP: |
| Lf->lts.type = 1; |
| Lf->lts.state.ui = (unsigned int)s->pst_pstate; |
| } |
| /* |
| * Enter local and remote addresses, being careful to generate |
| * proper IPv4 address alignment by copying, since IPv4 addresses |
| * may not be properly aligned in pst_boundaddr[] and pst_remaddr[]. |
| */ |
| if ((size_t)s->pst_boundaddr_len == sizeof(struct sockaddr_in)) { |
| sa = (struct sockaddr_in *)s->pst_boundaddr; |
| la = (unsigned char *)&sa->sin_addr; |
| lp = (int)htons(sa->sin_port); |
| } |
| if ((size_t)s->pst_remaddr_len == sizeof(struct sockaddr_in)) { |
| sa = (struct sockaddr_in *)s->pst_remaddr; |
| fp = (int)htons(sa->sin_port); |
| if ((sa->sin_addr.s_addr != INADDR_ANY) || fp) |
| fa = (unsigned char *)&sa->sin_addr; |
| } |
| if (fa || la) |
| (void) ent_inaddr(la, lp, fa, fp, AF_INET); |
| break; |
| |
| #if defined(HASIPv6) |
| case PS_AF_INET6: |
| af = AF_INET6; |
| if (Fnet && (!FnetTy || (FnetTy != 4))) |
| Lf->sf |= SELNET; |
| (void) snpf(Lf->type, sizeof(Lf->type), "IPv6"); |
| printpsproto(s->pst_protocol); |
| enter_dev_ch(print_kptr(na, (char *)NULL, 0)); |
| switch (s->pst_protocol) { |
| case PS_PROTO_TCP: |
| Lf->lts.type = 0; |
| Lf->lts.state.i = (int)s->pst_pstate; |
| break; |
| case PS_PROTO_UDP: |
| Lf->lts.type = 1; |
| Lf->lts.state.ui = (unsigned int)s->pst_pstate; |
| } |
| /* |
| * Enter local and remote addresses, being careful to generate |
| * proper IPv6 address alignment by copying, since IPv6 addresses |
| * may not be properly aligned in pst_boundaddr[] and pst_remaddr[]. |
| */ |
| if ((size_t)s->pst_boundaddr_len == sizeof(struct sockaddr_in6)) { |
| sa6 = (struct sockaddr_in6 *)s->pst_boundaddr; |
| la = (unsigned char *)&sa6->sin6_addr; |
| lp = (int)htons(sa6->sin6_port); |
| } |
| if ((size_t)s->pst_remaddr_len == sizeof(struct sockaddr_in6)) { |
| sa6 = (struct sockaddr_in6 *)s->pst_remaddr; |
| if ((fp = (int)htons(sa6->sin6_port)) |
| || !IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr)) |
| fa = (unsigned char *)&sa6->sin6_addr; |
| } |
| if (la || fa) { |
| if ((la && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)la)) |
| || (fa && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)fa))) |
| { |
| if (la) |
| la = (unsigned char *)IPv6_2_IPv4(la); |
| if (fa) |
| fa = (unsigned char *)IPv6_2_IPv4(fa); |
| af = AF_INET; |
| } |
| } |
| if (fa || la) |
| (void) ent_inaddr(la, lp, fa, fp, af); |
| break; |
| #endif /* defined(HASIPv6) */ |
| |
| case PS_AF_UNIX: |
| if (Funix) |
| Lf->sf |= SELUNX; |
| (void) snpf(Lf->type, sizeof(Lf->type), "unix"); |
| if (((len = (size_t)s->pst_boundaddr_len) > 0) |
| && (len <= sizeof(struct sockaddr_un))) |
| { |
| ua = (struct sockaddr_un *)s->pst_boundaddr; |
| if (ua->sun_path[0]) { |
| |
| /* |
| * The AF_UNIX socket has a bound address (file path). |
| * |
| * Save it. If there is a low nodeid, put that in |
| * parentheses after the name. If there is a low peer |
| * nodeid, put that in the parentheses, too. |
| */ |
| s->pst_boundaddr[PS_ADDR_SZ - 1] = '\0'; |
| if (s->pst_lo_nodeid) { |
| (void) snpf(buf, sizeof(buf), "(%s%s%s)", |
| print_kptr((KA_T)s->pst_lo_nodeid, |
| tbuf, sizeof(tbuf)), |
| s->pst_peer_lo_nodeid ? "->" : "", |
| s->pst_peer_lo_nodeid ? |
| print_kptr((KA_T)s->pst_peer_lo_nodeid, |
| (char *)NULL, 0) |
| : "" |
| ); |
| len = strlen(buf) + 1; |
| if (!(nma = (char *)malloc((MALLOC_S)len))) { |
| (void) fprintf(stderr, |
| "%s: no unix nma space(1): PID %ld, FD %s", |
| Pn, (long)Lp->pid, Lf->fd); |
| } |
| (void) snpf(nma, len, "%s", buf); |
| Lf->nma = nma; |
| } |
| /* |
| * Read the pst_filedetails for the bound address and process |
| * them as for a regular file. The already-entered file type, |
| * file name, size or offset, and name appendix will be |
| * preserved. |
| */ |
| if ((nau = read_det(&f->psf_fid, f->psf_hi_fileid, |
| f->psf_lo_fileid, f->psf_hi_nodeid, |
| f->psf_lo_nodeid, &pd))) |
| { |
| enter_nm(ua->sun_path); |
| (void) process_finfo(&pd, &f->psf_fid, &f->psf_id, nau); |
| return; |
| } else { |
| |
| /* |
| * Couldn't read file details. Erase any name appendix. |
| * Put the socket nodeid in the DEVICE column, put the |
| * bound address (path) in the NAME column, and build |
| * a new name appendix with the peer address. Add an |
| * error message if pstat_getfiledetails() set errno to |
| * something other than ENOENT. |
| */ |
| if ((err = errno) == ENOENT) |
| err = 0; |
| if (nma) { |
| (void) free((MALLOC_P *)nma); |
| Lf->nma = (char *)NULL; |
| } |
| if (s->pst_lo_nodeid) { |
| enter_dev_ch(print_kptr((KA_T)s->pst_lo_nodeid, |
| (char *)NULL, 0)); |
| } |
| (void) snpf(Namech, Namechl, "%s", ua->sun_path); |
| if (err || s->pst_peer_lo_nodeid) { |
| (void) snpf(buf, sizeof(buf), |
| "%s%s%s%s%s%s%s", |
| err ? "(Error: " : "", |
| err ? strerror(err) : "", |
| err ? ")" : "", |
| (err && s->pst_peer_lo_nodeid) ? " " : "", |
| s->pst_peer_lo_nodeid ? "(->" : "", |
| s->pst_peer_lo_nodeid ? |
| print_kptr((KA_T)s->pst_peer_lo_nodeid, |
| (char *)NULL, 0) |
| : "", |
| s->pst_peer_lo_nodeid ? ")" : "" |
| ); |
| len = strlen(buf) + 1; |
| if (!(nma = (char *)malloc((MALLOC_S)len))) { |
| (void) fprintf(stderr, |
| "%s: no unix nma space(2): PID %ld, FD %s", |
| Pn, (long)Lp->pid, Lf->fd); |
| } |
| (void) snpf(nma, len, "%s", buf); |
| Lf->nma = nma; |
| } |
| if (Sfile && is_file_named(ua->sun_path, 0)) |
| Lf->sf |= SELNM; |
| break; |
| } |
| } |
| } |
| /* |
| * If the UNIX socket has no bound address (file path), display the |
| * low nodeid in the DEVICE column and the peer's low nodeid in the |
| * NAME column. |
| */ |
| if (s->pst_peer_lo_nodeid) { |
| (void) snpf(Namech, Namechl, "->%s", |
| print_kptr((KA_T)s->pst_peer_lo_nodeid, (char *)NULL, 0)); |
| } |
| if (s->pst_lo_nodeid) |
| enter_dev_ch(print_kptr((KA_T)s->pst_lo_nodeid,(char *)NULL,0)); |
| break; |
| default: |
| (void) snpf(Namech, Namechl, "unsupported family: AF_%d", |
| s->pst_family); |
| } |
| if (Namech[0]) |
| enter_nm(Namech); |
| } |
| |
| |
| /* |
| * process_stream() -- process stream |
| */ |
| |
| void |
| process_stream(f, ckscko) |
| struct pst_fileinfo2 *f; /* pst_fileinfo2 */ |
| int ckscko; /* socket file only checking |
| * if 1 */ |
| { |
| struct clone *cl; |
| char *cp; |
| struct l_dev *dp = (struct l_dev *)NULL; |
| int hx, i, ncx, nsn, nsr; |
| size_t nb, nl; |
| KA_T na; |
| static int nsa = 0; |
| dev_t rdev; |
| static struct pst_stream *s = (struct pst_stream *)NULL; |
| struct pst_socket sck; |
| static size_t sz = sizeof(struct pst_stream); |
| |
| #if !defined(PS_STR_XPORT_DATA) |
| /* |
| * If socket file only checking is enabled and this HP-UX PSTAT instance |
| * doesn't support TCP or UDP stream eXPORT data, return without further |
| * action. |
| */ |
| if (ckscko == 1) |
| return; |
| #endif /* !defined(PS_STR_XPORT_DATA) */ |
| |
| /* |
| * Generate and save node ID. |
| */ |
| na = (KA_T)(((KA_T)(f->psf_hi_nodeid & 0xffffffff) << 32) |
| | (KA_T)(f->psf_lo_nodeid & 0xffffffff)); |
| |
| #if defined(HASFSTRUCT) |
| if (na && (Fsv & FSV_NI)) { |
| Lf->fna = na; |
| Lf->fsv |= FSV_NI; |
| } |
| #endif /* defined(HASFSTRUCT) */ |
| |
| /* |
| * Enter type. |
| */ |
| switch (f->psf_ftype) { |
| case PS_TYPE_STREAMS: |
| cp = "STR"; |
| break; |
| case PS_TYPE_SOCKET: |
| if (f->psf_subtype == PS_SUBTYPE_SOCKSTR) { |
| cp = "STSO"; |
| break; |
| } |
| /* fall through */ |
| default: |
| cp = "unkn"; |
| } |
| (void) snpf(Lf->type, sizeof(Lf->type), "%s", cp); |
| /* |
| * Allocate sufficient space for stream structures, then read them. |
| */ |
| if ((nsn = f->psf_nstrentt) && (nsn >= nsa)) { |
| nb = (size_t)(nsn * sizeof(struct pst_stream)); |
| if (s) |
| s = (struct pst_stream *)realloc((MALLOC_P *)s, nb); |
| else |
| s = (struct pst_stream *)malloc(nb); |
| if (!s) { |
| (void) fprintf(stderr, |
| "%s: no space for %ld pst_stream bytes\n", Pn, (long)nb); |
| Exit(1); |
| } |
| nsa = nsn; |
| } |
| errno = 0; |
| if ((nsr = pstat_getstream(s, sz, (size_t)nsn, 0, &f->psf_fid)) < 1) { |
| if (nsn) { |
| (void) snpf(Namech, Namechl, |
| "can't read %d stream structures%s%s", nsn, |
| errno ? ": " : "", errno ? strerror(errno) : ""); |
| enter_nm(Namech); |
| } else |
| enter_nm("no stream structures present"); |
| return; |
| } |
| /* |
| * Find the stream head. |
| */ |
| for (hx = 0; hx < nsn; hx++) { |
| if (s[hx].type == PS_STR_HEAD) |
| break; |
| } |
| if (hx >= nsn) { |
| enter_nm("no stream head located"); |
| return; |
| } |
| /* |
| * Make sure the stream head's fileid and nodeid match the ones in the |
| * pst_fileino2 structure. |
| */ |
| if ((f->psf_hi_fileid != s[hx].val.head.pst_hi_fileid) |
| | (f->psf_lo_fileid != s[hx].val.head.pst_lo_fileid) |
| | (f->psf_hi_nodeid != s[hx].val.head.pst_hi_nodeid) |
| | (f->psf_lo_nodeid != s[hx].val.head.pst_lo_nodeid)) { |
| enter_nm("no matching stream data available"); |
| return; |
| } |
| |
| #if defined(PS_STR_XPORT_DATA) |
| /* |
| * See if this stream has eXPORT data available and is a TCP or |
| * UDP stream. |
| */ |
| if ((s[hx].pst_extn_flags & PS_STR_XPORT_DATA) |
| && ((s[hx].pst_str_xport_protocol == PS_STR_XPORT_TCP_PROTO) |
| || (s[hx].pst_str_xport_protocol == PS_STR_XPORT_UDP_PROTO)) |
| ) { |
| |
| /* |
| * Make a socket from the eXPORT data and process it. |
| */ |
| (void) make_sock(f, &s[hx], &sck); |
| (void) process_socket(f, &sck); |
| return; |
| } else if (ckscko || Selinet) { |
| |
| /* |
| * If socket file or Internet file only processing is enabled, return. |
| */ |
| return; |
| } |
| #endif /* defined(PS_STR_XPORT_DATA) */ |
| |
| /* |
| * Enter size from stream head's structure, if requested. |
| */ |
| if (Fsize) { |
| if (Lf->access == 'r') { |
| Lf->sz = (SZOFFTYPE)s[hx].val.head.pst_rbytes; |
| Lf->sz_def = 1; |
| } else if (Lf->access == 'w') { |
| Lf->sz = (SZOFFTYPE)s[hx].val.head.pst_wbytes; |
| Lf->sz_def = 1; |
| } else if (Lf->access == 'u') { |
| Lf->sz = (SZOFFTYPE)s[hx].val.head.pst_rbytes |
| + (SZOFFTYPE)s[hx].val.head.pst_wbytes; |
| Lf->sz_def = 1; |
| } |
| } |
| /* |
| * Get the the device number from the stream head. |
| * |
| * If the stream is a clone: |
| * |
| * if there's a clone list, search it for the device, based on the stream |
| * head's minor device number only; |
| * if there's no clone list, search Devtp[], using a device number made |
| * from the stream head's major and minor device numbers; |
| * set the printable clone device number to one whose major device number |
| * is the stream head's minor device number, and whose minor device |
| * number is the stream head's device sequence number. |
| * |
| * If the stream isn't a clone, make the device number from the stream head's |
| * major and minor numbers, and look up the non-clone device number in Devtp[]. |
| */ |
| if (!Sdev) |
| readdev(0); |
| if (s[hx].val.head.pst_flag & PS_STR_ISACLONE) { |
| if (HaveCloneMaj && (CloneMaj == s[hx].val.head.pst_dev_major)) { |
| for (cl = Clone; cl; cl = cl->next) { |
| if (GET_MIN_DEV(Devtp[cl->dx].rdev) |
| == s[hx].val.head.pst_dev_minor) |
| { |
| dp = &Devtp[cl->dx]; |
| break; |
| } |
| } |
| } else { |
| rdev = makedev(s[hx].val.head.pst_dev_major, |
| s[hx].val.head.pst_dev_minor); |
| dp = lkupdev(&DevDev, &rdev, 0, 1); |
| } |
| rdev = makedev(s[hx].val.head.pst_dev_minor, |
| s[hx].val.head.pst_dev_seq); |
| } else { |
| rdev = makedev(s[hx].val.head.pst_dev_major, |
| s[hx].val.head.pst_dev_minor); |
| dp = lkupdev(&DevDev, &rdev, 0, 1); |
| } |
| Lf->dev = DevDev; |
| Lf->rdev = rdev; |
| Lf->dev_def = Lf->rdev_def = 1; |
| /* |
| * If the device was located, enter the device name and save the node number. |
| * |
| * If the device wasn't located, save a positive file ID number from the |
| * pst_fileinfo as a node number. |
| */ |
| if (dp) { |
| (void) snpf(Namech, Namechl, "%s", dp->name); |
| ncx = strlen(Namech); |
| Lf->inode = (INODETYPE)dp->inode; |
| Lf->inp_ty = 1; |
| } else { |
| ncx = (size_t)0; |
| if (f->psf_id.psf_fileid > 0) { |
| Lf->inode = (INODETYPE)f->psf_id.psf_fileid; |
| Lf->inp_ty = 1; |
| } |
| } |
| /* |
| * Enter stream module names. |
| */ |
| for (i = 1; i < nsr; i++) { |
| if (!(nl = strlen(s[i].val.module.pst_name))) |
| continue; |
| if (ncx) { |
| if ((ncx + 2) > (Namechl - 1)) |
| break; |
| (void) snpf(&Namech[ncx], Namechl - ncx, "->"); |
| ncx += 2; |
| } |
| if ((ncx + nl) > (Namechl - 1)) |
| break; |
| (void) snpf(Namech+ncx,Namechl-ncx,"%s",s[i].val.module.pst_name); |
| ncx += nl; |
| } |
| /* |
| * Set node type. |
| * |
| * Set offset defined if file size not requested or if no size was |
| * obtained from the stream head. |
| */ |
| Lf->ntype = N_STREAM; |
| Lf->is_stream = 1; |
| if (!Fsize || (Fsize && !Lf->sz_def)) |
| Lf->off_def = 1; |
| /* |
| * Test for specified file. |
| */ |
| if ((f->psf_subtype == PS_SUBTYPE_CHARDEV) |
| || (f->psf_subtype == PS_SUBTYPE_BLKDEV)) |
| i = 1; |
| else |
| i = 0; |
| if (Sfile && is_file_named((char *)NULL, i)) |
| Lf->sf |= SELNM; |
| /* |
| * Enter any name characters. |
| */ |
| if (Namech[0]) |
| enter_nm(Namech); |
| } |
| |
| |
| /* |
| * read_sock() -- read pst_socket info for file |
| */ |
| |
| struct pst_socket * |
| read_sock(f) |
| struct pst_fileinfo2 *f; /* file information */ |
| { |
| static struct pst_socket s; |
| |
| errno = 0; |
| if (f) { |
| if (pstat_getsocket(&s, sizeof(s), &f->psf_fid) > 0 |
| && f->psf_hi_fileid == s.pst_hi_fileid |
| && f->psf_lo_fileid == s.pst_lo_fileid |
| && f->psf_hi_nodeid == s.pst_hi_nodeid |
| && f->psf_lo_nodeid == s.pst_lo_nodeid) |
| return(&s); |
| } |
| return((struct pst_socket *)NULL); |
| } |