Print this page
XXXX adding PID information to netstat output

@@ -111,21 +111,10 @@
 
 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

@@ -764,10 +753,20 @@
                 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,11 +1743,12 @@
  * buffer allocation.
  */
 static int
 sockfs_update(kstat_t *ksp, int rw)
 {
-        uint_t  nactive = 0;            /* # of active AF_UNIX sockets  */
+        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,29 +1756,41 @@
                 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 = nactive * sizeof (struct k_sockinfo);
+        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 k_sockinfo       *pksi;  /* where we put sockinfo data   */
+        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,90 +1799,116 @@
 
         /*
          * for each sonode on the socklist, we massage the important
          * info into buf, in k_sockinfo format.
          */
-        pksi = (struct k_sockinfo *)buf;
+        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.
+                 * 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)(pksi) >= (caddr_t)buf + ksp->ks_data_size) {
+                if (((caddr_t)(psi) + sze) >
+                    ((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 =
+                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;
-                pksi->ks_si.si_ux_faddr_sou_magic =
+                psi->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;
+                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 (pksi->ks_si.si_laddr_sun_path));
+                            sizeof (psi->si_laddr_sun_path));
 
-                        pksi->ks_si.si_laddr_family =
+                        psi->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,
+                                (void) strncpy(psi->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);
+                                    sizeof (psi->si_laddr_sun_path));
+                                sn_len = strlen(psi->si_laddr_sun_path);
                         }
-                        pksi->ks_si.si_laddr_sun_path[sn_len] = 0;
+                        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 (pksi->ks_si.si_faddr_sun_path));
+                            sizeof (psi->si_faddr_sun_path));
 
-                        pksi->ks_si.si_faddr_family =
+                        psi->si_faddr_family =
                             sti->sti_faddr_sa->sa_family;
                         if (sn_len != 0) {
-                                (void) strncpy(pksi->ks_si.si_faddr_sun_path,
+                                (void) strncpy(psi->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);
+                                    sizeof (psi->si_faddr_sun_path));
+                                sn_len = strlen(psi->si_faddr_sun_path);
                         }
-                        pksi->ks_si.si_faddr_sun_path[sn_len] = 0;
+                        psi->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) sprintf(psi->si_son_straddr, "%p", (void *)so);
+                (void) sprintf(psi->si_lvn_straddr, "%p",
                     (void *)sti->sti_ux_laddr.soua_vp);
-                (void) sprintf(pksi->ks_straddr[2], "%p",
+                (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++;
-                pksi++;
         }
 
         ksp->ks_ndata = ns;
         return (0);
 }