blob: 50eae2a3aa416f44bd00dc2fb7e28c5a8f37b287 [file] [log] [blame]
/*
* dsock.c - Solaris socket processing functions for lsof
*/
/*
* Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
static char *rcsid = "$Id: dsock.c,v 1.31 2011/08/07 22:53:42 abe Exp $";
#endif
#include "lsof.h"
#if solaris>=110000
#include <inet/ipclassifier.h>
#endif /* solaris>=110000 */
#if defined(HAS_LIBCTF) && solaris>=110000
/*
* Icmp_t, rts_t and udp_t structure support for Solaris >=11 via libctf
*
* These structure definitions may look like kernel structures, but they
* are not. They have been defined to have member names that duplicate
* those used by the kernel that are of interest to lsof. Member valuess
* are obtained via the CTF library, libctf.
*
* Robert Byrnes developed the CTF library access code and contributed it
* to lsof.
*/
/*
* Icmp_t internal structure definition
*/
typedef struct icmp_s {
uint_t icmp_state; /* TPI state */
KA_T *icmp_connp; /* connection structure pointer */
in6_addr_t icmp_bound_v6src; /* Explicitely bound to address */
in6_addr_t icmp_v6src; /* Source address of this stream */
union {
uint_t icmp_dummy;
uint_t
icmp_Debug : 1, /* SO_DEBUG option */
icmp_dontroute : 1, /* SO_DONTROUTE option */
icmp_broadcast : 1, /* SO_BROADCAST option */
icmp_reuseaddr : 1, /* SO_REUSEADDR option */
icmp_useloopback : 1, /* SO_USELOOPBACK option */
icmp_hdrincl : 1, /* IP_HDRINCL option, etc. */
icmp_dgram_errind : 1, /* SO_DGRAM_ERRIND option */
icmp_pad : 25; /* pad to bit 31 */
} icmp_debug; /* This name identifies a single bit
* variable of the kernel's union, but
* CTF won't read individual bit
* variables, so for CTF's purposes
* it is declared as a uint_t union,
* named by the first bit variable of
* the kernel union, whose address CTF
* groks. */
} icmp_t;
/*
* Rts_t internal structure definition
*/
typedef struct rts_s {
uint_t rts_state; /* Provider interface state */
# if defined(HAS_CONN_NEW)
KA_T *rts_connp; /* connection structure pointer */
# endif /* defined(HAS_CONN_NEW) */
union {
uint_t rts_dummy;
uint_t
rts_Debug : 1, /* SO_DEBUG option */
rts_dontroute : 1, /* SO_DONTROUTE option */
rts_broadcast : 1, /* SO_BROADCAST option */
rts_reuseaddr : 1, /* SO_REUSEADDR option */
rts_useloopback : 1, /* SO_USELOOPBACK option */
icmp_pad : 27; /* padding to bit 31 */
} rts_debug; /* This name identifies a single bit
* variable, but CTF won't read
* individual bit variables, so for
* CTF's purposes it is declared as a
* uint_t union, named by its first
* bit variable, whose address CTF
* groks. */
} rts_t;
/*
* Udp_t internal structure definition
*/
typedef struct udp { uint_t udp_state; /* TPI state */
in_port_t udp_port; /* port bound to this stream */
in_port_t udp_dstport; /* connected port */
in6_addr_t udp_v6src; /* source address of this stream */
in6_addr_t udp_v6dst; /* connected destination */
ushort_t udp_ipversion; /* version -- IPV[46]_VERSION */
KA_T *udp_connp; /* connection structure pointer */
uint_t udp_bits; /* socket option bits */
} udp_t;
/*
* CTF definitions for icmp_t, rts_t and udp_t
*/
static int IRU_ctfs = 0; /* CTF initialization status for
* icmp_t, rts_t and udp_t */
# if defined(_LP64)
#define IRU_MOD_FORMAT "/kernel/%s/genunix"
#else /* !defined(_LP64) */
#define IRU_MOD_FORMAT "/kernel/genunix"
#endif /* defined(_LP64) */
/* genunix pathname template to which
* the kernel's instruction type set
* is added for CTF access to icmp_t,
* rts_t and udp_t */
/*
* Icmp_t, rts_t and udp_t access definitions and structures
*/
#define ICMP_T_TYPE_NAME "icmp_t"
static CTF_member_t icmp_t_members[] = {
CTF_MEMBER(icmp_state),
#define MX_icmp_state 0
# if defined(HAS_CONN_NEW)
CTF_MEMBER(icmp_connp),
#define MX_icmp_connp 1
# else /* !defined(HAS_CONN_NEW) */
CTF_MEMBER(icmp_bound_v6src),
#define MX_icmp_bound_v6src 1
CTF_MEMBER(icmp_v6src),
#define MX_icmp_v6src 2
CTF_MEMBER(icmp_debug),
#define MX_icmp_debug 3
# endif /* defined(HAS_CONN_NEW) */
{ NULL, 0 }
};
#define RTS_T_TYPE_NAME "rts_t"
static CTF_member_t rts_t_members[] = {
CTF_MEMBER(rts_state),
#define MX_rts_state 0
# if defined(HAS_CONN_NEW)
CTF_MEMBER(rts_connp),
#define MX_rts_connp 1
# else /* !defined(HAS_CONN_NEW) */
CTF_MEMBER(rts_debug),
#define MX_rts_debug 1
# endif /* defined(HAS_CONN_NEW) */
{ NULL, 0 }
};
#define UDP_T_TYPE_NAME "udp_t"
static CTF_member_t udp_t_members[] = {
CTF_MEMBER(udp_state),
#define MX_udp_state 0
CTF_MEMBER(udp_connp),
#define MX_udp_connp 1
# if !defined(HAS_CONN_NEW)
CTF_MEMBER(udp_port),
#define MX_udp_port 2
CTF_MEMBER(udp_dstport),
#define MX_udp_dstport 3
CTF_MEMBER(udp_v6src),
#define MX_udp_v6src 4
CTF_MEMBER(udp_v6dst),
#define MX_udp_v6dst 5
CTF_MEMBER(udp_ipversion),
#define MX_udp_ipversion 6
CTF_MEMBER(udp_bits),
#define MX_udp_bits 7
# endif /* !defined(HAS_CONN_NEW) */
{ NULL, 0 }
};
/*
* CTF icmp_t, rts_t and udp_t request table
*/
static CTF_request_t IRU_requests[] = {
{ ICMP_T_TYPE_NAME, icmp_t_members },
{ RTS_T_TYPE_NAME, rts_t_members },
{ UDP_T_TYPE_NAME, udp_t_members },
{ NULL, NULL }
};
/*
* Icmp_t, rts_t and udp_t function prototypes
*/
_PROTOTYPE(static int read_icmp_t,(KA_T va, KA_T ph, KA_T ia, icmp_t *ic));
_PROTOTYPE(static int read_rts_t,(KA_T va, KA_T ph, KA_T ra, rts_t *rt));
_PROTOTYPE(static int read_udp_t,(KA_T ua, udp_t *uc));
#endif /* defined(HAS_LIBCTF) && solaris>=110000 */
#if solaris<80000 || defined(HAS_IPCLASSIFIER_H)
/*
* Make sure the tcpb structure is always defined.
*/
typedef struct tcpb {
int dummy;
} tcpb_t;
#endif /* solaris<80000 || defined(HAS_IPCLASSIFIER_H) */
#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)
/*
* IPv_ADDR_UNSPEC() -- macro to test an IP[46] address for an unspecified
* address value
*/
#define IPv_ADDR_UNSPEC(af, p) \
(((af) == AF_INET6) ? (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)p)) \
: (((struct in_addr *)(p))->s_addr == INADDR_ANY))
#else /* !defined(HASIPv6) */
/*
* IPv_ADDR_UNSPEC() -- IPv4-only form of macro to test for an unspecified
* address value
*/
#define IPv_ADDR_UNSPEC(af, p) (((struct in_addr *)(p))->s_addr == INADDR_ANY)
#endif /* !defined(HASIPv6) */
#if defined(HASTCPOPT)
# if solaris==20600
#include <netinet/tcp.h>
# endif /* solaris==20600 */
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
# if defined(TH_TIMER_NEEDED)
#define ACK_TIMER TH_TIMER_NEEDED
# else
# if defined(TH_ACK_TIMER_NEEDED)
#define ACK_TIMER TH_ACK_TIMER_NEEDED
# endif /* defined(TH_ACK_TIMER_NEEDED) */
# endif /* defined(TH_TIMER_NEEDED */
#endif /* defined(HASTCPOPT) */
#if defined(HASSOOPT)
# if solaris<100000
#define KEEPALIVE_INTERVAL tcp_keepalive_intrvl
# else /* solaris>=100000 */
#define KEEPALIVE_INTERVAL tcp_ka_last_intrvl
# endif /* solaris<100000 */
#endif /* defined(HASSOOPT) */
/*
* Local function prototypes
*/
_PROTOTYPE(static void save_TCP_size,(tcp_t *tc));
_PROTOTYPE(static void save_TCP_states,(tcp_t *tc, caddr_t *fa, tcpb_t *tb,
caddr_t *xp));
/*
* build_IPstates() -- build the TCP and UDP state tables
*/
void
build_IPstates()
{
if (!TcpSt) {
(void) enter_IPstate("TCP", "CLOSED", TCPS_CLOSED);
(void) enter_IPstate("TCP", "IDLE", TCPS_IDLE);
(void) enter_IPstate("TCP", "BOUND", TCPS_BOUND);
(void) enter_IPstate("TCP", "LISTEN", TCPS_LISTEN);
(void) enter_IPstate("TCP", "SYN_SENT", TCPS_SYN_SENT);
(void) enter_IPstate("TCP", "SYN_RCVD", TCPS_SYN_RCVD);
(void) enter_IPstate("TCP", "ESTABLISHED", TCPS_ESTABLISHED);
(void) enter_IPstate("TCP", "CLOSE_WAIT", TCPS_CLOSE_WAIT);
(void) enter_IPstate("TCP", "FIN_WAIT_1", TCPS_FIN_WAIT_1);
(void) enter_IPstate("TCP", "CLOSING", TCPS_CLOSING);
(void) enter_IPstate("TCP", "LAST_ACK", TCPS_LAST_ACK);
(void) enter_IPstate("TCP", "FIN_WAIT_2", TCPS_FIN_WAIT_2);
(void) enter_IPstate("TCP", "TIME_WAIT", TCPS_TIME_WAIT);
(void) enter_IPstate("TCP", (char *)NULL, 0);
}
if (!UdpSt) {
(void) enter_IPstate("UDP", "Unbound", TS_UNBND);
(void) enter_IPstate("UDP", "Wait_BIND_REQ_Ack", TS_WACK_BREQ);
(void) enter_IPstate("UDP", "Wait_UNBIND_REQ_Ack", TS_WACK_UREQ);
(void) enter_IPstate("UDP", "Idle", TS_IDLE);
(void) enter_IPstate("UDP", "Wait_OPT_REQ_Ack", TS_WACK_OPTREQ);
(void) enter_IPstate("UDP", "Wait_CONN_REQ_Ack", TS_WACK_CREQ);
(void) enter_IPstate("UDP", "Wait_CONN_REQ_Confirm", TS_WCON_CREQ);
(void) enter_IPstate("UDP", "Wait_CONN_IND_Response", TS_WRES_CIND);
(void) enter_IPstate("UDP", "Wait_CONN_RES_Ack", TS_WACK_CRES);
(void) enter_IPstate("UDP", "Wait_Data_Xfr", TS_DATA_XFER);
(void) enter_IPstate("UDP", "Wait_Read_Release", TS_WIND_ORDREL);
(void) enter_IPstate("UDP", "Wait_Write_Release", TS_WREQ_ORDREL);
(void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", TS_WACK_DREQ6);
(void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", TS_WACK_DREQ7);
(void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", TS_WACK_DREQ9);
(void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", TS_WACK_DREQ10);
(void) enter_IPstate("UDP", "Wait_DISCON_REQ_Ack", TS_WACK_DREQ11);
(void) enter_IPstate("UDP", (char *)NULL, 0);
}
}
/*
* 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), "UNKNOWN_TCP_STATE_%d",
Lf->lts.state.i);
cp = sbuf;
} else
cp = TcpSt[i];
break;
case 1: /* TPI */
if (!UdpSt)
(void) build_IPstates();
if ((u = Lf->lts.state.ui + UdpStOff) < 0 || u >= UdpNstates) {
(void) snpf(sbuf, sizeof(sbuf), "UNKNOWN_UDP_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.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_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_DGRAM_ERRIND)
if (opt & SO_DGRAM_ERRIND) {
(void) printf("%cDGRAM_ERRIND", sep);
opt &= ~SO_DGRAM_ERRIND;
sep = ',';
}
# endif /* defined(SO_DGRAM_ERRIND) */
# if defined(SO_DONTROUTE)
if (opt & SO_DONTROUTE) {
(void) printf("%cDONTROUTE", sep);
opt &= ~SO_DONTROUTE;
sep = ',';
}
# endif /* defined(SO_DONTROUTE) */
# if defined(SO_KEEPALIVE)
if (opt & SO_KEEPALIVE) {
(void) printf("%cKEEPALIVE", sep);
if (Lf->lts.kai)
(void) printf("=%d", Lf->lts.kai);
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_OOBINLINE)
if (opt & SO_OOBINLINE) {
(void) printf("%cOOBINLINE", sep);
opt &= ~SO_OOBINLINE;
sep = ',';
}
# endif /* defined(SO_OOBINLINE) */
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_REUSEADDR)
if (opt & SO_REUSEADDR) {
(void) printf("%cREUSEADDR", sep);
opt &= ~SO_REUSEADDR;
sep = ',';
}
# endif /* defined(SO_REUSEADDR) */
if (Lf->lts.sbszs) {
(void) printf("%cSNDBUF=%lu", sep, Lf->lts.sbsz);
sep = ',';
}
# if defined(SO_TIMESTAMP)
if (opt & SO_TIMESTAMP) {
(void) printf("%cTIMESTAMP", sep);
opt &= ~SO_TIMESTAMP;
sep = ',';
}
# endif /* defined(SO_TIMESTAMP) */
# 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(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 (Lf->lts.msss) {
(void) printf("%cMSS=%lu", sep, Lf->lts.mss);
sep = ',';
}
# 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_SENTFIN)
if (topt & TF_SENTFIN) {
(void) printf("%cSENTFIN", sep);
topt &= ~TF_SENTFIN;
sep = ',';
}
# endif /* defined(TF_SENTFIN) */
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 (Ftcptpi && !Ffield && ps)
putchar(')');
if (nl)
putchar('\n');
}
#if solaris>=110000
/*
* procss_VSOCK() -- process a VSOCK socket
*/
# if defined(HAS_CONN_NEW)
/*
* Adjust for changes in the conn_s structure, introduced at OpenSolaris
* level b134.
*/
#define conn_ulp conn_proto
#define conn_rem V4_PART_OF_V6(connua_v6addr.connua_faddr)
#define conn_src V4_PART_OF_V6(connua_v6addr.connua_laddr)
# endif /* defined(HAS_CONN_NEW) */
int
process_VSOCK(va, v, so)
KA_T va; /* containing vnode address */
struct vnode *v; /* pointer to containing vnode */
struct sonode *so; /* pointer to socket's sonode */
{
int af; /* address family */
struct conn_s cs; /* connection info */
unsigned char *fa = (unsigned char *)NULL;
/* foreign address */
u_short fp = (u_short)0; /* foreign port */
u_short lp; /* local port */
icmp_t ic; /* ICMP control structure */
KA_T ka; /* temporary kernel address */
unsigned char *la = (unsigned char *)NULL;
/* local address */
KA_T pha; /* protocol handle address */
rts_t rt; /* AF_ROUTE control structure */
int s; /* state */
unsigned char *ta = (unsigned char *)NULL;
/* temporary address */
char tbuf[32], tbuf1[32]; /* temporary buffers */
tcp_t tc; /* TCP control structure */
tcph_t th; /* TCP header structure */
# if defined(HAS_CONN_NEW)
struct ip_xmit_attr_s xa;
caddr_t *xp = (caddr_t *)NULL;
# else /* !defined(HAS_CONN_NEW) */
tcph_t *tha = (tcph_t *)NULL; /* TCP header structure address */
# endif /* defined(HAS_CONN_NEW) */
char *ty; /* TCP type */
udp_t uc; /* local UDP control structure */
/*
* Read VSOCK's connection information. Enter its address as the protocol
* control block device address.
*/
if (!(pha = (KA_T)so->so_proto_handle))
return(0);
if (kread(pha, (char *)&cs, sizeof(cs))) {
(void) snpf(Namech, Namechl,
"vnode at %s; snode at %s; can't read proto handle at: %s",
print_kptr(va, tbuf, sizeof(tbuf)),
print_kptr((KA_T)v->v_data, tbuf1, sizeof(tbuf1)),
print_kptr(pha, (char *)NULL, 0));
Namech[Namechl - 1] = '\0';
enter_nm(Namech);
return(1);
}
enter_dev_ch(print_kptr(pha, (char *)NULL, 0));
/*
* Process connection info by protocol.
*/
switch ((af = so->so_family)) {
case AF_INET:
case AF_INET6:
/*
* Set INET type -- IPv4 or IPv6.
*/
if (af == AF_INET)
ty = "IPv4";
else
ty = "IPv6";
(void) snpf(Lf->type, sizeof(Lf->type), ty);
switch (cs.conn_ulp) {
case IPPROTO_TCP:
/*
* Process TCP socket; read its control structure.
*/
if (!(ka = (KA_T)cs.conn_proto_priv.cp_tcp)
|| kread(ka, (char *)&tc, sizeof(tc))
) {
(void) snpf(Namech, Namechl - 1,
"can't read TCP socket's control structure: %s",
print_kptr((KA_T)ka, (char *)NULL, 0));
Namech[Namechl - 1] = '\0';
enter_nm(Namech);
return(1);
}
/*
* Set TCP protcol name in Lf->iproto[].
*/
(void) snpf(Lf->iproto, IPROTOL - 1, "%s", "TCP");
Lf->iproto[IPROTOL - 1] = '\0';
Lf->inp_ty = 2;
/*
* Check for TCP state inclusion or exclusion.
*/
if (TcpNstates) {
if ((s = (int)tc.tcp_state + TcpStOff) < TcpNstates) {
if (TcpStXn) {
if (TcpStX[s]) {
Lf->sf |= SELEXCLF;
return(1);
}
}
if (TcpStIn) {
if (TcpStI[s]) {
TcpStI[s] = 2;
Lf->sf |= SELNET;
} else {
Lf->sf |= SELEXCLF;
return(1);
}
}
}
}
/*
* Set network file selection status.
*/
if (Fnet) {
if (!FnetTy
|| ((FnetTy == 4) && (af == AF_INET))
|| ((FnetTy == 6) && (af == AF_INET6))
) {
Lf->sf |= SELNET;
}
}
/*
* Save local and remote (foreign) TCP address.
*/
if (af == AF_INET6) {
ta = (unsigned char *)&cs.connua_v6addr.connua_faddr;
la = (unsigned char *)&cs.connua_v6addr.connua_laddr;
} else {
ta = (unsigned char *)&cs.conn_rem;
la = (unsigned char *)&cs.conn_src;
}
if (!IPv_ADDR_UNSPEC(af, ta) || (u_short)cs.conn_fport) {
fa = ta;
fp = (u_short)cs.conn_fport;
}
if ((af == AF_INET6)
&& ((la && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)la))
|| ((fa && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)fa))))
) {
/*
* Convert IPv4 addresses in IPv6 structures to IPv4 addresses
* in IPv4 structures. Change the address family to AF_INET.
*/
if (la)
la = (unsigned char *)IPv6_2_IPv4(la);
if (fa)
fa = (unsigned char *)IPv6_2_IPv4(fa);
af = AF_INET;
}
lp = (u_short)cs.conn_lport;
(void) ent_inaddr(la, (int)ntohs(lp), fa, (int)ntohs(fp), af);
/*
* Save TCP state information.
*/
# if defined(HAS_CONN_NEW)
if ((ka = (KA_T)cs.conn_ixa)
&& !kread(ka, (char *)&xa, sizeof(xa))
) {
xp = (caddr_t *)&xa;
}
(void) save_TCP_states(&tc, (caddr_t *)&cs, (tcpb_t *)NULL, xp);
# else /* !defined(HAS_CONN_NEW) */
if (tc.tcp_tcp_hdr_len
&& (ka = (KA_T)tc.tcp_tcph)
&& !kread(ka, (char *)&th, sizeof(th))
) {
tha = &th;
}
(void) save_TCP_states(&tc, (caddr_t *)tha, (tcpb_t *)NULL,
(caddr_t *)NULL);
# endif /* defined(HAS_CONN_NEW) */
Lf->lts.type = 0;
Lf->lts.state.i = (int)tc.tcp_state;
/*
* Save TCP size information.
*/
(void) save_TCP_size(&tc);
break;
case IPPROTO_UDP:
/*
* Process UDP socket; read its control structure.
*/
if (!(ka = (KA_T)cs.conn_proto_priv.cp_udp)
|| kread(ka, (char *)&uc, sizeof(uc))
) {
(void) snpf(Namech, Namechl - 1,
"can't read UDP socket's control structure: %s",
print_kptr((KA_T)ka, (char *)NULL, 0));
Namech[Namechl - 1] = '\0';
enter_nm(Namech);
return(1);
}
/*
* Set UDP protcol name in Lf->iproto[].
*/
(void) snpf(Lf->iproto, IPROTOL - 1, "%s", "UDP");
Lf->iproto[IPROTOL - 1] = '\0';
Lf->inp_ty = 2;
/*
* Check for UDP state inclusion or exclusion.
*/
if (UdpNstates) {
if ((s = (int)uc.udp_state + TcpStOff) < UdpNstates) {
if (UdpStXn) {
if (UdpStX[s]) {
Lf->sf |= SELEXCLF;
return(1);
}
}
if (UdpStIn) {
if (UdpStI[s]) {
UdpStI[s] = 2;
Lf->sf |= SELNET;
} else {
Lf->sf |= SELEXCLF;
return(1);
}
}
}
}
/*
* Set network file selection status.
*/
if (Fnet) {
if (!FnetTy
|| ((FnetTy == 4) && (af == AF_INET))
|| ((FnetTy == 6) && (af == AF_INET6))
) {
Lf->sf |= SELNET;
}
}
/*
* Save local and remote (foreign) UDP address.
*/
if (af == AF_INET6) {
ta = (unsigned char *)&cs.connua_v6addr.connua_faddr;
la = (unsigned char *)&cs.connua_v6addr.connua_laddr;
} else {
ta = (unsigned char *)&cs.conn_rem;
la = (unsigned char *)&cs.conn_src;
}
if (!IPv_ADDR_UNSPEC(af, ta) || (u_short)cs.conn_fport) {
fa = ta;
fp = (u_short)cs.conn_fport;
}
lp = (u_short)cs.conn_lport;
(void) ent_inaddr(la, (int)ntohs(lp), fa, (int)ntohs(fp), af);
/*
* Save UDP state and size information.
*/
if (!Fsize)
Lf->off_def = 1;
Lf->lts.type = 1;
Lf->lts.state.ui = (unsigned int)uc.udp_state;
# if defined(HASSOOPT)
/*
* Save UDP flags.
*/
if (Ftcptpi & TCPTPI_FLAGS) {
union {
uint_t flags;
uint_t
udpb_debug : 1, /* SO_DEBUG option */
udpb_dontroute : 1, /* SO_DONTROUTE option */
udpb_broadcast : 1, /* SO_BROADCAST option */
udpb_reuseaddr : 1, /* SO_REUSEADDR option */
udpb_useloopback : 1, /* SO_USELOOPBACK option */
udpb_dgram_errind : 1, /* SO_DGRAM_ERRIND option */
udpb_pad : 26; /* pad to bit 31 */
} ucf;
ucf.flags = uc.udp_bits;
if (ucf.udpb_debug)
Lf->lts.opt |= SO_DEBUG;
if (ucf.udpb_dontroute)
Lf->lts.opt |= SO_DONTROUTE;
if (ucf.udpb_broadcast)
Lf->lts.opt |= SO_BROADCAST;
if (ucf.udpb_reuseaddr)
Lf->lts.opt |= SO_REUSEADDR;
if (ucf.udpb_useloopback)
Lf->lts.opt |= SO_USELOOPBACK;
if (ucf.udpb_dgram_errind)
Lf->lts.opt |= SO_DGRAM_ERRIND;
}
# endif /* defined(HASSOOPT) */
break;
case IPPROTO_ICMP:
case IPPROTO_ICMPV6:
/*
* Process ICMP or ICMP6 socket.
*
* Set protocol name.
*/
if (cs.conn_ulp == IPPROTO_ICMP)
ty = "ICMP";
else
ty = "ICMP6";
(void) snpf(Lf->iproto, IPROTOL - 1, "%s", ty);
Lf->iproto[IPROTOL - 1] = '\0';
Lf->inp_ty = 2;
/*
* Read the ICMP control structure.
*/
if (read_icmp_t(va, pha, (KA_T)cs.conn_proto_priv.cp_icmp, &ic))
return(1);
/*
* Save ICMP size and state information.
*/
if (!Fsize)
Lf->off_def = 1;
Lf->lts.type = 1;
Lf->lts.state.ui = (unsigned int)ic.icmp_state;
/*
* Set network file selection status.
*/
if (Fnet) {
if (!FnetTy
|| ((FnetTy == 4) && (af == AF_INET))
|| ((FnetTy == 6) && (af == AF_INET6))
) {
Lf->sf |= SELNET;
}
}
/*
* Save addresses.
*/
ta = (af == AF_INET6) ? (unsigned char *)&ic.icmp_bound_v6src
: (unsigned char *)&V4_PART_OF_V6(ic.icmp_bound_v6src);
if (!IPv_ADDR_UNSPEC(af, ta))
la = ta;
ta = (af == AF_INET6) ? (unsigned char *)&ic.icmp_v6src
: (unsigned char *)&V4_PART_OF_V6(ic.icmp_v6src);
if (!IPv_ADDR_UNSPEC(af, ta))
fa = ta;
if (la || fa)
(void)ent_inaddr(la, 0, fa, 0, af);
# if defined(HASSOOPT)
/*
* Save ICMP flags.
*/
if (Ftcptpi & TCPTPI_FLAGS) {
if (ic.icmp_debug.icmp_Debug)
Lf->lts.opt |= SO_DEBUG;
if (ic.icmp_debug.icmp_dontroute)
Lf->lts.opt |= SO_DONTROUTE;
if (ic.icmp_debug.icmp_broadcast)
Lf->lts.opt |= SO_BROADCAST;
if (ic.icmp_debug.icmp_reuseaddr)
Lf->lts.opt |= SO_REUSEADDR;
if (ic.icmp_debug.icmp_useloopback)
Lf->lts.opt |= SO_USELOOPBACK;
if (ic.icmp_debug.icmp_dgram_errind)
Lf->lts.opt |= SO_DGRAM_ERRIND;
}
# endif /* defined(HASSOOPT) */
break;
default:
(void) snpf(Namech, Namechl - 1,
"unsupported conn_s AF_INET%s protocol: %u",
(af == AF_INET6) ? "6" : "",
(unsigned int)cs.conn_ulp);
Namech[Namechl - 1] = '\0';
enter_nm(Namech);
return(1);
}
break;
case AF_ROUTE:
/*
* Set INET type -- IPv4 or IPv6.
*/
if (af == AF_INET)
ty = "IPv4";
else
ty = "IPv6";
(void) snpf(Lf->type, sizeof(Lf->type), ty);
/*
* Set protocol name.
*/
(void) strncpy(Lf->iproto, "ROUTE", IPROTOL - 1);
Lf->iproto[IPROTOL - 1] = '\0';
Lf->inp_ty = 2;
/*
* Read routing control structure.
*/
if (read_rts_t(va, pha, (KA_T)cs.conn_proto_priv.cp_rts, &rt))
return(1);
/*
/*
* Save AF_ROUTE size and state information.
*/
if (!Fsize)
Lf->off_def = 1;
Lf->lts.type = 1;
Lf->lts.state.i = (int)rt.rts_state;
/*
* Set network file selection status.
*/
if (Fnet) {
if (!FnetTy
|| ((FnetTy == 4) && (af == AF_INET))
|| ((FnetTy == 6) && (af == AF_INET6))
) {
Lf->sf |= SELNET;
}
}
# if defined(HASSOOPT)
/*
* Save ROUTE flags.
*/
if (Ftcptpi & TCPTPI_FLAGS) {
if (rt.rts_debug.rts_Debug)
Lf->lts.opt |= SO_DEBUG;
if (rt.rts_debug.rts_dontroute)
Lf->lts.opt |= SO_DONTROUTE;
if (rt.rts_debug.rts_broadcast)
Lf->lts.opt |= SO_BROADCAST;
if (rt.rts_debug.rts_reuseaddr)
Lf->lts.opt |= SO_REUSEADDR;
if (rt.rts_debug.rts_useloopback)
Lf->lts.opt |= SO_USELOOPBACK;
}
# endif /* defined(HASSOOPT) */
break;
default:
(void) printiproto((int)cs.conn_ulp);
(void) snpf(Namech, Namechl - 1, "unsupported socket family: %u",
so->so_family);
Namech[Namechl - 1] = '\0';
enter_nm(Namech);
Lf->inp_ty = 2;
}
return(1);
}
#endif /* solaris>=110000*/
/*
* process_socket() - process Solaris socket
*/
void
process_socket(sa, ty)
KA_T sa; /* stream's data address in kernel */
char *ty; /* socket type name */
{
int af;
unsigned char *fa = (unsigned char *)NULL;
int fp = 0;
int i, lp;
#if solaris<110000
# if solaris>=100000 && defined(HAS_IPCLASSIFIER_H)
struct conn_s ic;
#define ipc_v6laddr conn_srcv6
#define ipc_v6faddr conn_remv6
#define ipc_fport conn_fport
#define ipc_lport conn_lport
# else /* solaris<100000 || !defined(HAS_IPCLASSIFIER_H) */
struct ipc_s ic;
# endif /* solaris>=100000 && defined(HAS_IPCLASSIFIER_H) */
#else /* solaris>=110000 */
struct conn_s cs;
#endif /* solaris<110000 */
int ics = 0;
unsigned char *la = (unsigned char *)NULL;
struct module_info mi;
KA_T ka;
u_short p;
KA_T pcb = (KA_T)NULL;
struct queue q;
struct qinit qi;
KA_T qp;
u_short *s;
struct stdata sd;
unsigned char *ta;
char tbuf[32];
#if solaris<20600
struct tcp_s { /* should come from kernel source
* file ../uts/common/inet/tcp.c */
# if solaris>=20400
struct tcp_s *d1[8];
# endif /* solaris>=20400 */
# if defined(P101318) && P101318>=32
struct tcp_s *d1[6];
# endif /* defined(P101318) && P101318>=32 */
int tcp_state;
queue_t *d3[2];
mblk_t *d4[2];
u_long d5;
mblk_t *d6;
u_long d7;
u_long tcp_snxt; /* Senders next seq num */
u_long tcp_suna; /* Sender unacknowledged */
u_long tcp_swnd; /* Senders window (relative to suna) */
u_long d8[5];
int tcp_hdr_len; /* combined TCP/IP header length */
tcph_t *tcp_tcph; /* pointer to combined header */
int d9;
unsigned int d10;
int d11;
mblk_t *d12;
long d13;
mblk_t *d14;
u_long d15;
# if solaris<20400 && (!defined(P101318) || P101318<32)
mblk_t *d16;
# endif /* solaris<20400 && (!defined(P101318) || P101318<32) */
unsigned int d17;
u_long tcp_rnxt; /* Seq we expect to recv next */
u_long tcp_rwnd; /* Current receive window */
u_long d18;
long d19[2];
mblk_t *d20[4];
u_long d21[5];
long d22[3];
# if solaris<20500
u_long d23[2];
u_long tcp_rack; /* Seq # we have acked */
# else /* solaris>=20500 */
u_long d23[3];
# endif /* solaris<20500 */
# if solaris<20400
u_long d24[28];
# else /* solaris>=20400 */
# if solaris<20500
u_long d24[67];
# else /* solaris>=20500 */
# if solaris<20501
u_long d25[6];
# else /* solaris>=20501 */
u_long d25[8];
# endif /* solaris<20501 */
u_long tcp_rack; /* Seq # we have acked */
# if solaris<20501
u_long d26[29];
# else /* solaris>=20501 */
u_long d26[33];
# endif /* solaris>=20501 */
# endif /* solaris<20500 */
# endif /* solaris<20400 */
iph_t tcp_iph;
} tc;
#else /* solaris>=20600 */
struct tcp_s tc;
#endif /* solaris<20600 */
#if solaris>=80000 && !defined(HAS_IPCLASSIFIER_H)
tcpb_t tcb;
#endif /* solaris>=80000 && !defined(HAS_IPCLASSIFIER_H) */
tcpb_t *tcbp = (tcpb_t *)NULL;
int tcs = 0;
tcph_t th;
tcph_t *tha = (tcph_t *)NULL;
#if solaris<110000
struct ud_s { /* should come from kernel source
* file ../uts/common/inet/udp.c */
uint udp_state; /* TPI state */
unsigned char d1[2];
unsigned char udp_port[2]; /* port bound to this stream */
unsigned char udp_src[4]; /* source address of this stream */
} uc;
#else /* solaris>=110000 */
udp_t uc; /* UDP control structure */
#endif /* solaris<110000 */
int ucs = 0;
#if defined(HASIPv6)
if (strrchr(ty, '6')) {
(void) snpf(Lf->type, sizeof(Lf->type), "IPv6");
af = AF_INET6;
} else {
(void) snpf(Lf->type, sizeof(Lf->type), "IPv4");
af = AF_INET;
}
#else /* !defined(HASIPv6) */
(void) snpf(Lf->type, sizeof(Lf->type), "inet");
af = AF_INET;
#endif /* defined(HASIPv6) */
/*
* Set network file selection status.
*/
if (Fnet) {
if (!FnetTy
|| ((FnetTy == 4) && (af == AF_INET))
#if defined(HASIPv6)
|| ((FnetTy == 6) && (af == AF_INET6))
#endif /* defined(HASIPv6) */
) {
if (!TcpStIn && !UdpStIn)
Lf->sf |= SELNET;
}
}
Lf->inp_ty = 2;
/*
* Convert type to upper case protocol name.
*/
if (ty) {
for (i = 0; (ty[i] != '\0') && (i < IPROTOL) && (i < 3); i++) {
if (islower((unsigned char)ty[i]))
Lf->iproto[i] = toupper((unsigned char)ty[i]);
else
Lf->iproto[i] = ty[i];
}
} else
i = 0;
Lf->iproto[i] = '\0';
/*
* Read stream queue entries to obtain private IP, TCP, and UDP structures.
*/
if (!sa || readstdata(sa, &sd))
qp = (KA_T)NULL;
else
qp = (KA_T)sd.sd_wrq;
for (i = 0; qp && i < 20; i++, qp = (KA_T)q.q_next) {
if (kread(qp, (char *)&q, sizeof(q)))
break;
if ((ka = (KA_T)q.q_qinfo) == (KA_T)NULL
|| kread(ka, (char *)&qi, sizeof(qi)))
continue;
if ((ka = (KA_T)qi.qi_minfo) == (KA_T)NULL
|| kread(ka, (char *)&mi, sizeof(mi))
|| (ka = (KA_T)mi.mi_idname) == (KA_T)NULL)
continue;
if (kread(ka, (char *)&tbuf, sizeof(tbuf) - 1))
continue;
if ((pcb = (KA_T)q.q_ptr) == (KA_T)NULL)
continue;
#if solaris<110000
if (strncasecmp(tbuf, "IP", 2) == 0) {
if (kread(pcb, (char *)&ic, sizeof(ic)) == 0)
ics = 1;
continue;
}
#endif /* solaris<110000 */
if (strncasecmp(tbuf, "TCP", 3) == 0) {
#if solaris<=90000 || !defined(HAS_IPCLASSIFIER_H)
if (!kread((KA_T)pcb, (char *)&tc, sizeof(tc)))
# if solaris>=80000
{
if (tc.tcp_base
&& !kread((KA_T)tc.tcp_base, (char *)&tcb, sizeof(tcb))) {
tcs = 1;
tcbp = &tcb;
}
tc.tcp_base = &tcb; /* support for macros */
tcb.tcpb_tcp = &tc; /* support for macros */
}
# else /* solaris<80000 */
tcs = 1;
# endif /* solaris>=80000 */
#else /* solaris>90000 && defined(HAS_IPCLASSIFIER_H) */
# if solaris>=110000
if (!kread(pcb, (char *)&cs, sizeof(cs))
&& (cs.conn_ulp == IPPROTO_TCP)
) {
ics = 1;
if ((ka = (KA_T)cs.conn_proto_priv.cp_tcp)
&& !kread(ka, (char *)&tc, sizeof(tc))
) {
tcs = 1;
}
}
# else /* solaris<110000 */
if (!kread((KA_T)pcb, (char *)&ic, sizeof(ic))
&& ic.conn_tcp
&& !kread((KA_T)ic.conn_tcp, (char *)&tc, sizeof(tc))
) {
ics = tcs = 1;
}
# endif /* solaris>=110000 */
#endif /* solaris<=90000 || !defined(HAS_IPCLASSIFIER_H) */
if (tcs && TcpNstates) {
int s = (int)tc.tcp_state + TcpStOff;
/*
* Check for TCP state inclusion or exclusion.
*/
if (s < TcpNstates) {
if (TcpStXn) {
if (TcpStX[s]) {
Lf->sf &= ~SELNET;
Lf->sf |= SELEXCLF;
return;
}
}
if (TcpStIn) {
if (TcpStI[s]) {
TcpStI[s] = 2;
Lf->sf |= SELNET;
} else {
Lf->sf &= ~SELNET;
Lf->sf |= SELEXCLF;
return;
}
}
}
}
if (!(Lf->sf & SELNET) && !TcpStIn && UdpStIn) {
if (Fnet) {
if (!FnetTy
|| (FnetTy == 4) && (af == AF_INET)
#if defined(HASIPv6)
|| (FnetTy == 6) && (af == AF_INET6)
#endif /* defined(HASIPv6) */
) {
Lf->sf |= SELNET;
}
}
}
continue;
}
if (strncasecmp(tbuf, "UDP", 3) == 0) {
#if solaris<110000
if (kread(pcb, (char *)&uc, sizeof(uc)) == 0)
ucs = 1;
#else /* solaris>=110000 */
if (!kread(pcb, (char *)&cs, sizeof(cs))
&& (cs.conn_ulp == IPPROTO_UDP)
) {
ics = 1;
if ((ka = (KA_T)cs.conn_proto_priv.cp_udp)
&& !read_udp_t(ka, &uc)
) {
ucs = 1;
}
}
#endif /* solaris<110000 */
if (ucs && UdpNstates) {
unsigned int s = (unsigned int)uc.udp_state + UdpStOff;
/*
* Check for UDP state inclusion or exclusion.
*/
if (s < UdpNstates) {
if (UdpStXn) {
if (UdpStX[s]) {
Lf->sf &= ~SELNET;
Lf->sf |= SELEXCLF;
return;
}
}
if (UdpStIn) {
if (UdpStI[s]) {
UdpStI[s] = 2;
Lf->sf |= SELNET;
} else {
Lf->sf |= SELEXCLF;
return;
}
}
}
}
if (!(Lf->sf & SELNET) && TcpStIn && !UdpStIn) {
if (Fnet) {
if (!FnetTy
|| (FnetTy == 4) && (af == AF_INET)
#if defined(HASIPv6)
|| (FnetTy == 6) && (af == AF_INET6)
#endif /* defined(HASIPv6) */
) {
Lf->sf |= SELNET;
}
}
}
continue;
}
}
if (ics) {
/*
* Print stream head's q_ptr address as protocol control block address.
*/
if (pcb)
enter_dev_ch(print_kptr(pcb, (char *)NULL, 0));
if (strncmp(Lf->iproto, "UDP", 3) == 0) {
/*
* Save UDP address and TPI state.
*/
#if solaris<20600
la = (unsigned char *)&ic.ipc_udp_addr;
p = (u_short)ic.ipc_udp_port;
#else /* solaris>=20600 */
# if solaris>=110000
af = (uc.udp_ipversion == IPV6_VERSION) ? AF_INET6 : AF_INET;
la = (af == AF_INET6) ? (unsigned char *)&uc.udp_v6src
: (unsigned char *)&V4_PART_OF_V6(uc.udp_v6src);
p = (u_short)uc.udp_port;
# else /* solaris<110000 */
# if defined(HASIPv6)
la = (af == AF_INET6) ? (unsigned char *)&ic.ipc_v6laddr
: (unsigned char *)IPv6_2_IPv4(&ic.ipc_v6laddr);
# else /* !defined(HASIPv6 */
la = (unsigned char *)&ic.ipc_laddr;
# endif /* defined(HASIPv6) */
p = (u_short)ic.ipc_lport;
# endif /* solaris>=110000 */
#endif /* solaris<20600 */
#if solaris<110000
if (IPv_ADDR_UNSPEC(af, la) && !p && ucs) {
/*
* If the ipc_s structure has no local address, use
* the port in the ud_s structure.
*/
s = (u_short *)&uc.udp_port[0];
p = *s;
}
# if defined(HASIPv6)
if ((af == AF_INET6) && la
&& IN6_IS_ADDR_V4MAPPED((struct in6_addr *)la)) {
/*
* Convert a local IPv4 address in an IPv6 structure to an IPv4
* address in an IPv4 structure. Change the address family to
* AF_INET.
*/
la = (unsigned char *)IPv6_2_IPv4(la);
af = AF_INET;
}
# endif /* defined(HASIPv6) */
#endif /* solaris<110000 */
(void) ent_inaddr(la, (int)ntohs(p), (unsigned char *)NULL,
-1, af);
if (!Fsize)
Lf->off_def = 1;
if (ucs) {
Lf->lts.type = 1;
Lf->lts.state.ui = (unsigned int)uc.udp_state;
}
} else if (strncmp(Lf->iproto, "TCP", 3) == 0) {
if (ics) {
/*
* Save TCP address.
*/
#if solaris<20400
la = (unsigned char *)&ic.ipc_tcp_addr[0];
p = (u_short)ic.ipc_tcp_addr[5];
#else /* solaris>=20400 */
# if solaris<20600
la = (unsigned char *)&ic.ipc_tcp_laddr;
p = (u_short)((short *)&ic.ipc_tcp_ports)[1];
# else /* solaris>=20600 */
# if solaris>=110000
la = (af == AF_INET6)
? (unsigned char *)&cs.connua_v6addr.connua_laddr
: (unsigned char *)&cs.conn_src;
lp = cs.conn_lport;
# else /* solaris<110000 */
# if defined(HASIPv6)
la = (af == AF_INET6) ? (unsigned char *)&ic.ipc_v6laddr
: (unsigned char *)IPv6_2_IPv4(&ic.ipc_v6laddr);
# else /* !defined(HASIPv6 */
la = (unsigned char *)&ic.ipc_laddr;
# endif /* defined(HASIPv6) */
p = (u_short)ic.ipc_lport;
# endif /* solaris>=110000 */
# endif /* solaris<20600 */
#endif /* solaris<20400 */
#if solaris<110000
if (IPv_ADDR_UNSPEC(af, la) && !p && tcs) {
/*
* If the ipc_s structure has no local address, use the
* local address in the stream's tcp_iph structure (except
* for Solaris 2.4), and the port number in the stream's
* tcph structure.
*/
# if solaris!=20400 && solaris<80000
la = (unsigned char *)&tc.tcp_iph.iph_src[0];
# else /* solaris==20400 || solaris<80000 */
# if solaris>=100000 && defined(HAS_IPCLASSIFIER_H)
la = (af == AF_INET6) ? (unsigned char *)&ic.conn_srcv6
: (unsigned char *)IPv6_2_IPv4(&ic.conn_srcv6);
# else /* solaris<100000 || !defined(HAS_IPCLASSIFIER_H) */
# if solaris>=80000
# if defined(HASIPv6)
la = (af == AF_INET6)
? (unsigned char *)&tcb.tcpb_ip_src_v6
: (unsigned char *)IPv6_2_IPv4(&tcb.tcpb_ip_src_v6);
# else /* !defined(HASIPv6) */
la = (unsigned char *)&tcb.tcpb_ip_src;
# endif /* defined(HASIPv6) */
# endif /* solaris>=80000 */
# endif /* solaris>=100000 && defined(HAS_IPCLASSIFIER_H) */
# endif /* solaris!=20400 && !defined(HASIPv6) */
if (tc.tcp_hdr_len && tc.tcp_tcph
&& !kread((KA_T)tc.tcp_tcph, (char *)&th, sizeof(th))
) {
tha = &th;
s = (u_short *)&th.th_lport[0];
p = *s;
}
}
#endif /* solaris<110000 */
lp = (int)ntohs(p);
#if solaris<20400
if ((int)ic.ipc_tcp_addr[2] != INADDR_ANY
|| ic.ipc_tcp_addr[4] != 0)
{
fa = (unsigned char *)&ic.ipc_tcp_addr[2];
fp = (int)ntohs(ic.ipc_tcp_addr[4]);
}
#else /* solaris>=20400 */
# if solaris<20600
if ((int)ic.ipc_tcp_faddr != INADDR_ANY
|| ((u_short *) &ic.ipc_tcp_ports)[0] != 0)
{
fa = (unsigned char *)&ic.ipc_tcp_faddr;
fp = (int)ntohs(((u_short *)&ic.ipc_tcp_ports)[0]);
}
# else /* solaris>=20600 */
# if solaris>=110000
ta = (af == AF_INET6)
? (unsigned char *)&cs.connua_v6addr.connua_faddr
: (unsigned char *)&cs.conn_rem;
if (!IPv_ADDR_UNSPEC(af, ta) || ((u_short)cs.conn_fport)) {
fa = ta;
fp = (u_short)cs.conn_fport;
}
# else /* solaris<110000 */
# if defined(HASIPv6)
ta = (af == AF_INET6) ? (unsigned char *)&ic.ipc_v6faddr
: (unsigned char *)IPv6_2_IPv4(&ic.ipc_v6faddr);
# else /* !defined(HASIPv6) */
ta = (unsigned char *)&ic.ipc_faddr;
# endif /* defined(HASIPv6) */
if (!IPv_ADDR_UNSPEC(af, ta) || ((u_short)ic.ipc_fport)) {
fa = ta;
fp = (int)ntohs(((u_short)ic.ipc_fport));
}
# endif /* solaris>=110000 */
# endif /* solaris<20600 */
#endif /* solaris <20400 */
#if defined(HASIPv6)
if ((af == AF_INET6)
&& ((la && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)la))
|| ((fa && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)fa))))
) {
/*
* Convert IPv4 addresses in IPv6 structures to IPv4
* addresses in IPv4 structures. Change the address
* family to AF_INET.
*/
if (la)
la = (unsigned char *)IPv6_2_IPv4(la);
if (fa)
fa = (unsigned char *)IPv6_2_IPv4(fa);
af = AF_INET;
}
#endif /* defined(HASIPv6) */
if (fa || la)
(void) ent_inaddr(la, lp, fa, fp, af);
}
/*
* Save TCP state information.
*/
if (tcs) {
(void) save_TCP_states(&tc, (caddr_t *)tha, tcbp,
(caddr_t *)NULL);
Lf->lts.type = 0;
Lf->lts.state.i = (int)tc.tcp_state;
}
/*
* Save TCP size information.
*/
if (tcs)
(void) save_TCP_size(&tc);
}
} else
(void) strcat(Namech, "no TCP/UDP/IP information available");
/*
* Enter name characters if there are some.
*/
if (Namech[0])
enter_nm(Namech);
}
#if solaris>=110000
/*
* read_icmp_t() - read connections icmp_t info
*/
static int
read_icmp_t(va, ph, ia, ic)
KA_T va; /* containing vnode kernel address */
KA_T ph; /* containing protocol handle kernel
* address */
KA_T ia; /* icmp_t structure's kernel address */
icmp_t *ic; /* local icmp_t receiver */
{
char tbuf[32], tbuf1[32]; /* print_kptr() temporary buffers */
# if defined(HAS_CONN_NEW)
struct conn_s cs; /* connection structure */
KA_T ka; /* kernel address */
zeromem((char *)ic, sizeof(icmp_t));
# endif /* defined(HAS_CONN_NEW) */
(void) CTF_init(&IRU_ctfs, IRU_MOD_FORMAT, IRU_requests);
if (!ia
|| CTF_MEMBER_READ(ia, ic, icmp_t_members, icmp_state)
# if defined(HAS_CONN_NEW)
|| CTF_MEMBER_READ(ia, ic, icmp_t_members, icmp_connp)
# else /* !defined(HAS_CONN_NEW) */
|| CTF_MEMBER_READ(ia, ic, icmp_t_members, icmp_bound_v6src)
|| CTF_MEMBER_READ(ia, ic, icmp_t_members, icmp_v6src)
|| CTF_MEMBER_READ(ia, ic, icmp_t_members, icmp_debug)
# endif /* defined(HAS_CONN_NEW) */
) {
(void) snpf(Namech, Namechl - 1,
"vnode at %s; proto handle at %s; can't read icmp_t at %s",
print_kptr(va, tbuf, sizeof(tbuf)),
print_kptr(ph, tbuf1, sizeof(tbuf1)),
print_kptr(ia, (char *)NULL, 0));
Namech[Namechl - 1] = '\0';
enter_nm(Namech);
return(1);
}
# if defined(HAS_CONN_NEW)
if ((ka = (KA_T)ic->icmp_connp)
&& !kread(ka, (char *)&cs, sizeof(cs)))
{
struct ip_xmit_attr_s xa;
/*
* Complete the icmp_t structure from the conn_s structure.
*/
ic->icmp_bound_v6src = cs.conn_bound_addr_v6;
ic->icmp_v6src = cs.conn_saddr_v6;
ic->icmp_debug.icmp_Debug = cs.conn_debug;
ic->icmp_debug.icmp_broadcast = cs.conn_broadcast;
ic->icmp_debug.icmp_reuseaddr = cs.conn_reuseaddr;
ic->icmp_debug.icmp_useloopback = cs.conn_useloopback;
ic->icmp_debug.icmp_dgram_errind = cs.conn_dgram_errind;
if ((ka = (KA_T)cs.conn_ixa)
&& !kread(ka, (char *)&xa, sizeof(xa))
) {
ic->icmp_debug.icmp_dontroute = (xa.ixa_flags & IXAF_DONTROUTE)
? 1 : 0;
}
}
# endif /* defined(HAS_CONN_NEW) */
return(0);
}
/*
* read_rts_t() - read connections rts_t info
*/
static int
read_rts_t(va, ph, ra, rt)
KA_T va; /* containing vnode kernel address */
KA_T ph; /* containing protocol handle kernel
* address */
KA_T ra; /* rts_t structure's kernel address */
rts_t *rt; /* local rts_t receiver */
{
char tbuf[32], tbuf1[32]; /* print_kptr() temporary buffers */
# if defined(HAS_CONN_NEW)
struct conn_s cs; /* connextion structure */
KA_T ka; /* kernal address */
zeromem((char *)rt, sizeof(rts_t));
# endif /* defined(HAS_CONN_NEW) */
(void) CTF_init(&IRU_ctfs, IRU_MOD_FORMAT, IRU_requests);
if (!ra
|| CTF_MEMBER_READ(ra, rt, rts_t_members, rts_state)
# if defined(HAS_CONN_NEW)
|| CTF_MEMBER_READ(ra, rt, rts_t_members, rts_connp)
# else /* !defined(HAS_CONN_NEW) */
|| CTF_MEMBER_READ(ra, rt, rts_t_members, rts_debug)
# endif /* defined(HAS_CONN_NEW) */
) {
(void) snpf(Namech, Namechl - 1,
"vnode at %s; proto handle at %s; can't read rts_t at %s",
print_kptr(va, tbuf, sizeof(tbuf)),
print_kptr(ph, tbuf1, sizeof(tbuf1)),
print_kptr(ra, (char *)NULL, 0));
Namech[Namechl - 1] = '\0';
enter_nm(Namech);
return(1);
}
# if defined(HAS_CONN_NEW)
if ((ka = (KA_T)rt->rts_connp)
&& !kread(ka, (char *)&cs, sizeof(struct conn_s))
) {
struct ip_xmit_attr_s xa;
/*
* Fill in rts_debug from the connection structure.
*/
rt->rts_debug.rts_Debug = cs.conn_debug;
rt->rts_debug.rts_broadcast = cs.conn_broadcast;
rt->rts_debug.rts_reuseaddr = cs.conn_reuseaddr;
rt->rts_debug.rts_useloopback = cs.conn_useloopback;
if ((ka = (KA_T)cs.conn_ixa)
&& !kread(ka, (char *)&xa, sizeof(xa))
) {
rt->rts_debug.rts_dontroute = (xa.ixa_flags & IXAF_DONTROUTE)
? 1 : 0;
}
}
# endif /* defined(HAS_CONN_NEW) */
return(0);
}
/*
* read_udp_t() - read UDP control structure
*/
static int
read_udp_t(ua, uc)
KA_T ua; /* ucp_t kernel address */
udp_t *uc; /* receiving udp_t structure */
{
(void) CTF_init(&IRU_ctfs, IRU_MOD_FORMAT, IRU_requests);
if (!ua
|| CTF_MEMBER_READ(ua, uc, udp_t_members, udp_state)
# if defined(HAS_CONN_NEW)
|| CTF_MEMBER_READ(ua, uc, udp_t_members, udp_connp)
# else /* !defined(HAS_CONN_NEW) */
|| CTF_MEMBER_READ(ua, uc, udp_t_members, udp_port)
|| CTF_MEMBER_READ(ua, uc, udp_t_members, udp_dstport)
|| CTF_MEMBER_READ(ua, uc, udp_t_members, udp_v6src)
|| CTF_MEMBER_READ(ua, uc, udp_t_members, udp_v6dst)
|| CTF_MEMBER_READ(ua, uc, udp_t_members, udp_ipversion)
|| CTF_MEMBER_READ(ua, uc, udp_t_members, udp_bits)
# endif /* defined(HAS_CONN_NEW) */
) {
(void) snpf(Namech, Namechl, "can't read udp_t: %s",
print_kptr(ua, (char *)NULL, 0));
Namech[Namechl - 1] = '\0';
enter_nm(Namech);
return(1);
}
return(0);
}
#endif /* solaris>=110000 */
/*
* save_TCP_size() -- save TCP size information
*/
static void
save_TCP_size(tc)
tcp_t *tc; /* pointer to TCP control structure */
{
int rq, sq;
#if defined(HASTCPTPIQ) || defined(HASTCPTPIW)
# if defined(HASTCPTPIW)
Lf->lts.rw = (int)tc->tcp_rwnd;
Lf->lts.ww = (int)tc->tcp_swnd;
Lf->lts.rws = Lf->lts.wws = 1;
# endif /* defined(HASTCPTPIW) */
if ((rq = (int)tc->tcp_rnxt - (int)tc->tcp_rack) < 0)
rq = 0;
if ((sq = (int)tc->tcp_snxt - (int)tc->tcp_suna - 1) < 0)
sq = 0;
# if defined(HASTCPTPIQ)
Lf->lts.rq = (unsigned long)rq;
Lf->lts.sq = (unsigned long)sq;
Lf->lts.rqs = Lf->lts.sqs = 1;
# endif /* defined(HASTCPTPIQ) */
if (Fsize) {
if (Lf->access == 'r')
Lf->sz = (SZOFFTYPE)rq;
else if (Lf->access == 'w')
Lf->sz = (SZOFFTYPE)sq;
else
Lf->sz = (SZOFFTYPE)(rq + sq);
Lf->sz_def = 1;
} else
Lf->off_def = 1;
#else /* !defined(HASTCPTPIQ) && !defined(HASTCPTPIW) */
Lf->off_def = 1;
#endif /* defined(HASTCPTPIQ) || defined(HASTCPTPIW) */
}
/*
* save_TCP_states() - save TCP states
*/
static void
save_TCP_states(tc, fa, tb, xp)
tcp_t *tc; /* pointer to TCP control structure */
caddr_t *fa; /* flags address (may be NULL):
* if HAS_CONN_NEW: conn_s *
* if !CONN_HAS_NEW: tcph_t *
*/
tcpb_t *tb; /* pointer to TCP base structure (may
* be NULL) */
caddr_t *xp; /* pointer to struct ip_xmit_attr_s if
* HAS_CONN_NEW (may be NULL) */
{
if (!tc)
return;
#if defined(HASSOOPT)
# if defined(HAS_CONN_NEW)
if (Ftcptpi & TCPTPI_FLAGS && fa) {
struct conn_s *cs = (struct conn_s *)fa;
if (cs->conn_broadcast)
Lf->lts.opt |= SO_BROADCAST;
if (cs->conn_debug)
Lf->lts.opt |= SO_DEBUG;
if (cs->conn_dgram_errind)
Lf->lts.opt |= SO_DGRAM_ERRIND;
if (xp && (((ip_xmit_attr_t *)xp)->ixa_flags & IXAF_DONTROUTE))
Lf->lts.opt |= SO_DONTROUTE;
if (cs->conn_keepalive) {
Lf->lts.opt |= SO_KEEPALIVE;
Lf->lts.kai = (unsigned int)tc->tcp_ka_interval;
}
if (cs->conn_linger) {
Lf->lts.opt |= SO_LINGER;
Lf->lts.ltm = (unsigned int)cs->conn_lingertime;
}
if (cs->conn_oobinline)
Lf->lts.opt |= SO_OOBINLINE;
Lf->lts.pqlen = (unsigned int)tc->tcp_conn_req_cnt_q0;
Lf->lts.qlen = (unsigned int)tc->tcp_conn_req_cnt_q;
Lf->lts.qlim = (unsigned int)tc->tcp_conn_req_max;
Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims
= (unsigned char)1;
if (cs->conn_reuseaddr)
Lf->lts.opt |= SO_REUSEADDR;
if (cs->conn_useloopback)
Lf->lts.opt |= SO_USELOOPBACK;
# else /* !defined(HAS_CONN_NEW) */
if (Ftcptpi & TCPTPI_FLAGS) {
if (tc->tcp_broadcast)
Lf->lts.opt |= SO_BROADCAST;
if (tc->tcp_debug)
Lf->lts.opt |= SO_DEBUG;
if (tc->tcp_dgram_errind)
Lf->lts.opt |= SO_DGRAM_ERRIND;
if (tc->tcp_dontroute)
Lf->lts.opt |= SO_DONTROUTE;
if (tc->KEEPALIVE_INTERVAL) {
Lf->lts.opt |= SO_KEEPALIVE;
Lf->lts.kai = (unsigned int)tc->KEEPALIVE_INTERVAL;
}
if (tc->tcp_linger) {
Lf->lts.opt |= SO_LINGER;
Lf->lts.ltm = (unsigned int)tc->tcp_lingertime;
}
if (tc->tcp_oobinline)
Lf->lts.opt |= SO_OOBINLINE;
Lf->lts.pqlen = (unsigned int)tc->tcp_conn_req_cnt_q0;
Lf->lts.qlen = (unsigned int)tc->tcp_conn_req_cnt_q;
Lf->lts.qlim = (unsigned int)tc->tcp_conn_req_max;
Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims
= (unsigned char)1;
# if solaris>=80000
# if defined(HAS_IPCLASSIFIER_H)
if (tc->tcp_reuseaddr)
# else /* !defined(HAS_IPCLASSIFIER_H) */
if (tb && tb->tcpb_reuseaddr)
# endif /* !defined(HAS_IPCLASSIFIER_H) */
Lf->lts.opt |= SO_REUSEADDR;
# endif /* solaris>=80000 */
if (tc->tcp_useloopback)
Lf->lts.opt |= SO_USELOOPBACK;
# endif /* defined(HAS_CONN_NEW) */
#endif /* defined(HASSOOPT) */
#if defined(HASTCPOPT)
# if defined(ACK_TIMER)
# if !defined(HAS_CONN_NEW)
if (fa && (((tcph_t *)fa)->th_flags[0] & ACK_TIMER))
Lf->lts.topt |= TF_DELACK;
# endif /* !defined(HAS_CONN_NEW) */
# endif /* defined(ACK_TIMER) */
# if solaris<80000 || defined(HAS_IPCLASSIFIER_H)
Lf->lts.mss = (unsigned long)tc->tcp_mss;
# else /* solaris>=80000 && !defined(HAS_IPCLASSIFIER_H) */
if (tb)
Lf->lts.mss = (unsigned long)tb->tcpb_mss;
# endif /* solaris<80000 || defined(HAS_IPCLASSIFIER_H) */
Lf->lts.msss = (unsigned char)1;
if (tc->tcp_naglim == 1L)
Lf->lts.topt |= TF_NODELAY;
if (tc->tcp_fin_sent)
Lf->lts.topt |= TF_SENTFIN;
}
#endif /* defined(HASTCPOPT) */
}