1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*
  28  * Copyright 2012 David Hoeppner.  All rights reserved.
  29  */
  30 
  31 /*
  32  * Functions related to MIB-II and kstat.
  33  */
  34 
  35 #include <sys/types.h>
  36 #include <sys/tihdr.h>
  37 #include <sys/policy.h>
  38 #include <sys/tsol/tnet.h>
  39 
  40 #include <inet/common.h>
  41 #include <inet/ip.h>
  42 #include <inet/kstatcom.h>
  43 #include <inet/snmpcom.h>
  44 
  45 #include <sys/cmn_err.h>
  46 
  47 #include "dccp_impl.h"
  48 
  49 static int dccp_snmp_state(dccp_t *);
  50 
  51 static int
  52 dccp_snmp_state(dccp_t *dccp)
  53 {
  54         if (dccp == NULL) {
  55                 return (0);
  56         }
  57 
  58         switch(dccp->dccp_state) {
  59         case DCCPS_CLOSED:
  60                 return (MIB2_DCCP_closed);
  61         default:
  62                 return (0);
  63         }
  64 }
  65 
  66 /*
  67  * Get the MIB-II stats.
  68  */
  69 mblk_t *
  70 dccp_snmp_get(queue_t *q, mblk_t *mpctl)
  71 {
  72         conn_t          *connp = Q_TO_CONN(q);
  73         connf_t         *connfp;
  74         ip_stack_t      *ips;
  75         dccp_stack_t    *dccps;
  76         struct opthdr   *optp;
  77         mblk_t          *mp2ctl;
  78         mblk_t          *mpdata;
  79         mblk_t          *mp_conn_ctl = NULL;
  80         mblk_t          *mp_conn_tail;
  81         mblk_t          *mp_attr_ctl = NULL;
  82         mblk_t          *mp_attr_tail;
  83         size_t          dccp_mib_size;
  84         size_t          dce_size;
  85         zoneid_t        zoneid;
  86         int             i;
  87         mib2_dccpConnEntry_t    dce;
  88 
  89         mp2ctl = copymsg(mpctl);
  90 
  91         if (mpctl == NULL ||
  92             (mpdata = mpctl->b_cont) == NULL ||
  93             (mp_conn_ctl = copymsg(mpctl)) == NULL ||
  94             (mp_attr_ctl = copymsg(mpctl)) == NULL) {
  95                 freemsg(mp_conn_ctl);
  96                 freemsg(mp_attr_ctl);
  97                 freemsg(mpctl);
  98                 freemsg(mp2ctl);
  99                 return (NULL);
 100         }
 101 
 102         ips = connp->conn_netstack->netstack_ip;
 103         dccps = connp->conn_netstack->netstack_dccp;
 104         dce_size = sizeof (mib2_dccpConnEntry_t);
 105         zoneid = Q_TO_CONN(q)->conn_zoneid;
 106 
 107         for (i = 0; i < CONN_G_HASH_SIZE; i++) {
 108                 ips = dccps->dccps_netstack->netstack_ip;
 109 
 110                 connfp = &ips->ips_ipcl_globalhash_fanout[i];
 111                 connp = NULL;
 112 
 113                 while ((connp = ipcl_get_next_conn(connfp, connp,
 114                     IPCL_DCCPCONN)) != NULL) {
 115                         dccp_t  *dccp;
 116 
 117                         if (connp->conn_zoneid != zoneid) {
 118                                 continue;
 119                         }
 120 
 121                         dccp = connp->conn_dccp;
 122 
 123                         dce.dccpConnState = dccp_snmp_state(dccp);
 124 
 125                         if (connp->conn_ipversion == IPV4_VERSION ||
 126                             (dccp->dccp_state <= DCCPS_LISTEN)) {
 127                                 dce.dccpConnRemAddress =
 128                                     connp->conn_faddr_v4;
 129                                 dce.dccpConnLocalAddress =
 130                                     connp->conn_laddr_v4;
 131                         }
 132 
 133                         dce.dccpConnLocalPort = ntohs(connp->conn_lport);
 134                         dce.dccpConnRemPort = ntohs(connp->conn_fport);
 135 
 136                         dce.dccpConnCreationProcess = (connp->conn_cpid < 0) ?
 137                             MIB2_UNKNOWN_PROCESS : connp->conn_cpid;
 138                         dce.dccpConnCreationTime = connp->conn_open_time;
 139 
 140                         (void) snmp_append_data2(mp_conn_ctl->b_cont,
 141                             &mp_conn_tail, (char *)&dce, dce_size);
 142                 }
 143         }
 144 
 145         optp = (struct opthdr *)&mp_conn_ctl->b_rptr[
 146             sizeof (struct T_optmgmt_ack)];
 147         optp->level = MIB2_DCCP;
 148         optp->name = MIB2_DCCP_CONN;
 149         optp->len = msgdsize(mp_conn_ctl->b_cont);
 150         qreply(q, mp_conn_ctl);
 151 
 152         return (mp2ctl);
 153 }