Print this page
XXXX adding PID information to netstat output
*** 111,131 ****
extern void nl7c_init(void);
extern int modrootloaded;
- #define ADRSTRLEN (2 * sizeof (void *) + 1)
- /*
- * kernel structure for passing the sockinfo data back up to the user.
- * the strings array allows us to convert AF_UNIX addresses into strings
- * with a common method regardless of which n-bit kernel we're running.
- */
- struct k_sockinfo {
- struct sockinfo ks_si;
- char ks_straddr[3][ADRSTRLEN];
- };
-
/*
* Translate from a device pathname (e.g. "/dev/tcp") to a vnode.
* Returns with the vnode held.
*/
int
--- 111,120 ----
*** 764,773 ****
--- 753,772 ----
mutex_enter(&fp->f_tlock);
fp->f_count++;
mutex_exit(&fp->f_tlock);
setf(fd, fp);
*rp++ = fd;
+
+ /*
+ * Add the current pid to the list associated with this
+ * descriptor.
+ */
+ if (fp->f_vnode != NULL)
+ (void) VOP_IOCTL(fp->f_vnode, F_ASSOCI_PID,
+ (intptr_t)curproc->p_pidp->pid_id, FKIOCTL, kcred,
+ NULL, NULL);
+
if (AU_AUDITING())
audit_fdrecv(fd, fp);
dprint(1, ("fdbuf_extract: [%d] = %d, %p refcnt %d\n",
i, fd, (void *)fp, fp->f_count));
}
*** 1744,1754 ****
* buffer allocation.
*/
static int
sockfs_update(kstat_t *ksp, int rw)
{
! uint_t nactive = 0; /* # of active AF_UNIX sockets */
struct sonode *so; /* current sonode on socklist */
zoneid_t myzoneid = (zoneid_t)(uintptr_t)ksp->ks_private;
ASSERT((zoneid_t)(uintptr_t)ksp->ks_private == getzoneid());
--- 1743,1754 ----
* buffer allocation.
*/
static int
sockfs_update(kstat_t *ksp, int rw)
{
! uint_t n, nactive = 0; /* # of active AF_UNIX sockets */
! uint_t tsze = 0;
struct sonode *so; /* current sonode on socklist */
zoneid_t myzoneid = (zoneid_t)(uintptr_t)ksp->ks_private;
ASSERT((zoneid_t)(uintptr_t)ksp->ks_private == getzoneid());
*** 1756,1784 ****
return (EACCES);
}
for (so = socklist.sl_list; so != NULL; so = SOTOTPI(so)->sti_next_so) {
if (so->so_count != 0 && so->so_zoneid == myzoneid) {
nactive++;
}
}
ksp->ks_ndata = nactive;
! ksp->ks_data_size = nactive * sizeof (struct k_sockinfo);
return (0);
}
static int
sockfs_snapshot(kstat_t *ksp, void *buf, int rw)
{
int ns; /* # of sonodes we've copied */
struct sonode *so; /* current sonode on socklist */
! struct k_sockinfo *pksi; /* where we put sockinfo data */
t_uscalar_t sn_len; /* soa_len */
zoneid_t myzoneid = (zoneid_t)(uintptr_t)ksp->ks_private;
sotpi_info_t *sti;
ASSERT((zoneid_t)(uintptr_t)ksp->ks_private == getzoneid());
ksp->ks_snaptime = gethrtime();
if (rw == KSTAT_WRITE) { /* bounce all writes */
--- 1756,1796 ----
return (EACCES);
}
for (so = socklist.sl_list; so != NULL; so = SOTOTPI(so)->sti_next_so) {
if (so->so_count != 0 && so->so_zoneid == myzoneid) {
+
nactive++;
+
+ mutex_enter(&so->so_pid_tree_lock);
+ n = avl_numnodes(&so->so_pid_tree);
+ mutex_exit(&so->so_pid_tree_lock);
+
+ tsze += sizeof (struct sockinfo);
+ tsze += (n > 1) ? ((n - 1) * sizeof (pid_t)) : 0;
}
}
ksp->ks_ndata = nactive;
! ksp->ks_data_size = tsze;
return (0);
}
static int
sockfs_snapshot(kstat_t *ksp, void *buf, int rw)
{
int ns; /* # of sonodes we've copied */
struct sonode *so; /* current sonode on socklist */
! struct sockinfo *psi; /* where we put sockinfo data */
t_uscalar_t sn_len; /* soa_len */
zoneid_t myzoneid = (zoneid_t)(uintptr_t)ksp->ks_private;
sotpi_info_t *sti;
+ uint_t sze;
+ mblk_t *mblk;
+ conn_pid_info_t *cpi;
+
ASSERT((zoneid_t)(uintptr_t)ksp->ks_private == getzoneid());
ksp->ks_snaptime = gethrtime();
if (rw == KSTAT_WRITE) { /* bounce all writes */
*** 1787,1876 ****
/*
* for each sonode on the socklist, we massage the important
* info into buf, in k_sockinfo format.
*/
! pksi = (struct k_sockinfo *)buf;
ns = 0;
for (so = socklist.sl_list; so != NULL; so = SOTOTPI(so)->sti_next_so) {
/* only stuff active sonodes and the same zone: */
if (so->so_count == 0 || so->so_zoneid != myzoneid) {
continue;
}
/*
* If the sonode was activated between the update and the
! * snapshot, we're done - as this is only a snapshot.
*/
! if ((caddr_t)(pksi) >= (caddr_t)buf + ksp->ks_data_size) {
break;
}
sti = SOTOTPI(so);
/* copy important info into buf: */
! pksi->ks_si.si_size = sizeof (struct k_sockinfo);
! pksi->ks_si.si_family = so->so_family;
! pksi->ks_si.si_type = so->so_type;
! pksi->ks_si.si_flag = so->so_flag;
! pksi->ks_si.si_state = so->so_state;
! pksi->ks_si.si_serv_type = sti->sti_serv_type;
! pksi->ks_si.si_ux_laddr_sou_magic =
sti->sti_ux_laddr.soua_magic;
! pksi->ks_si.si_ux_faddr_sou_magic =
sti->sti_ux_faddr.soua_magic;
! pksi->ks_si.si_laddr_soa_len = sti->sti_laddr.soa_len;
! pksi->ks_si.si_faddr_soa_len = sti->sti_faddr.soa_len;
! pksi->ks_si.si_szoneid = so->so_zoneid;
! pksi->ks_si.si_faddr_noxlate = sti->sti_faddr_noxlate;
mutex_enter(&so->so_lock);
if (sti->sti_laddr_sa != NULL) {
ASSERT(sti->sti_laddr_sa->sa_data != NULL);
sn_len = sti->sti_laddr_len;
ASSERT(sn_len <= sizeof (short) +
! sizeof (pksi->ks_si.si_laddr_sun_path));
! pksi->ks_si.si_laddr_family =
sti->sti_laddr_sa->sa_family;
if (sn_len != 0) {
/* AF_UNIX socket names are NULL terminated */
! (void) strncpy(pksi->ks_si.si_laddr_sun_path,
sti->sti_laddr_sa->sa_data,
! sizeof (pksi->ks_si.si_laddr_sun_path));
! sn_len = strlen(pksi->ks_si.si_laddr_sun_path);
}
! pksi->ks_si.si_laddr_sun_path[sn_len] = 0;
}
if (sti->sti_faddr_sa != NULL) {
ASSERT(sti->sti_faddr_sa->sa_data != NULL);
sn_len = sti->sti_faddr_len;
ASSERT(sn_len <= sizeof (short) +
! sizeof (pksi->ks_si.si_faddr_sun_path));
! pksi->ks_si.si_faddr_family =
sti->sti_faddr_sa->sa_family;
if (sn_len != 0) {
! (void) strncpy(pksi->ks_si.si_faddr_sun_path,
sti->sti_faddr_sa->sa_data,
! sizeof (pksi->ks_si.si_faddr_sun_path));
! sn_len = strlen(pksi->ks_si.si_faddr_sun_path);
}
! pksi->ks_si.si_faddr_sun_path[sn_len] = 0;
}
mutex_exit(&so->so_lock);
! (void) sprintf(pksi->ks_straddr[0], "%p", (void *)so);
! (void) sprintf(pksi->ks_straddr[1], "%p",
(void *)sti->sti_ux_laddr.soua_vp);
! (void) sprintf(pksi->ks_straddr[2], "%p",
(void *)sti->sti_ux_faddr.soua_vp);
ns++;
- pksi++;
}
ksp->ks_ndata = ns;
return (0);
}
--- 1799,1914 ----
/*
* for each sonode on the socklist, we massage the important
* info into buf, in k_sockinfo format.
*/
! psi = (struct sockinfo *)buf;
ns = 0;
for (so = socklist.sl_list; so != NULL; so = SOTOTPI(so)->sti_next_so) {
/* only stuff active sonodes and the same zone: */
if (so->so_count == 0 || so->so_zoneid != myzoneid) {
continue;
}
+ mblk = so_get_sock_pid_mblk((sock_upper_handle_t)so);
+ if (mblk == NULL) {
+ continue;
+ }
+ cpi = (conn_pid_info_t *)mblk->b_datap->db_base;
+ sze = sizeof (struct sockinfo);
+ sze += (cpi->cpi_pids_cnt > 1) ?
+ ((cpi->cpi_pids_cnt - 1) * sizeof (pid_t)) : 0;
+
/*
* If the sonode was activated between the update and the
! * snapshot, we're done - as this is only a snapshot. We need
! * to make sure that we have space for this sockinfo. In the
! * time window between the update and the snapshot, the size of
! * sockinfo may change, as new pids are added/removed to/from
! * the list. We have to take that into consideration and only
! * include the sockinfo if we have enough space. That means the
! * number of entries we return by snapshot might not equal the
! * the number of entries calculated by update.
*/
! if (((caddr_t)(psi) + sze) >
! ((caddr_t)buf + ksp->ks_data_size)) {
break;
}
sti = SOTOTPI(so);
/* copy important info into buf: */
! psi->si_size = sze;
! psi->si_family = so->so_family;
! psi->si_type = so->so_type;
! psi->si_flag = so->so_flag;
! psi->si_state = so->so_state;
! psi->si_serv_type = sti->sti_serv_type;
! psi->si_ux_laddr_sou_magic =
sti->sti_ux_laddr.soua_magic;
! psi->si_ux_faddr_sou_magic =
sti->sti_ux_faddr.soua_magic;
! psi->si_laddr_soa_len = sti->sti_laddr.soa_len;
! psi->si_faddr_soa_len = sti->sti_faddr.soa_len;
! psi->si_szoneid = so->so_zoneid;
! psi->si_faddr_noxlate = sti->sti_faddr_noxlate;
!
mutex_enter(&so->so_lock);
if (sti->sti_laddr_sa != NULL) {
ASSERT(sti->sti_laddr_sa->sa_data != NULL);
sn_len = sti->sti_laddr_len;
ASSERT(sn_len <= sizeof (short) +
! sizeof (psi->si_laddr_sun_path));
! psi->si_laddr_family =
sti->sti_laddr_sa->sa_family;
if (sn_len != 0) {
/* AF_UNIX socket names are NULL terminated */
! (void) strncpy(psi->si_laddr_sun_path,
sti->sti_laddr_sa->sa_data,
! sizeof (psi->si_laddr_sun_path));
! sn_len = strlen(psi->si_laddr_sun_path);
}
! psi->si_laddr_sun_path[sn_len] = 0;
}
if (sti->sti_faddr_sa != NULL) {
ASSERT(sti->sti_faddr_sa->sa_data != NULL);
sn_len = sti->sti_faddr_len;
ASSERT(sn_len <= sizeof (short) +
! sizeof (psi->si_faddr_sun_path));
! psi->si_faddr_family =
sti->sti_faddr_sa->sa_family;
if (sn_len != 0) {
! (void) strncpy(psi->si_faddr_sun_path,
sti->sti_faddr_sa->sa_data,
! sizeof (psi->si_faddr_sun_path));
! sn_len = strlen(psi->si_faddr_sun_path);
}
! psi->si_faddr_sun_path[sn_len] = 0;
}
mutex_exit(&so->so_lock);
! (void) sprintf(psi->si_son_straddr, "%p", (void *)so);
! (void) sprintf(psi->si_lvn_straddr, "%p",
(void *)sti->sti_ux_laddr.soua_vp);
! (void) sprintf(psi->si_fvn_straddr, "%p",
(void *)sti->sti_ux_faddr.soua_vp);
+ psi->si_pids[0] = 0;
+ if ((psi->si_pn_cnt = cpi->cpi_pids_cnt) > 0) {
+ (void) memcpy(psi->si_pids, cpi->cpi_pids,
+ psi->si_pn_cnt * sizeof (pid_t));
+ }
+
+ freemsg(mblk);
+
+ psi = (struct sockinfo *)((caddr_t)psi + psi->si_size);
ns++;
}
ksp->ks_ndata = ns;
return (0);
}