15dd46ab5SKacheong Poon /* 25dd46ab5SKacheong Poon * CDDL HEADER START 35dd46ab5SKacheong Poon * 45dd46ab5SKacheong Poon * The contents of this file are subject to the terms of the 55dd46ab5SKacheong Poon * Common Development and Distribution License (the "License"). 65dd46ab5SKacheong Poon * You may not use this file except in compliance with the License. 75dd46ab5SKacheong Poon * 85dd46ab5SKacheong Poon * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95dd46ab5SKacheong Poon * or http://www.opensolaris.org/os/licensing. 105dd46ab5SKacheong Poon * See the License for the specific language governing permissions 115dd46ab5SKacheong Poon * and limitations under the License. 125dd46ab5SKacheong Poon * 135dd46ab5SKacheong Poon * When distributing Covered Code, include this CDDL HEADER in each 145dd46ab5SKacheong Poon * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155dd46ab5SKacheong Poon * If applicable, add the following below this CDDL HEADER, with the 165dd46ab5SKacheong Poon * fields enclosed by brackets "[]" replaced with your own identifying 175dd46ab5SKacheong Poon * information: Portions Copyright [yyyy] [name of copyright owner] 185dd46ab5SKacheong Poon * 195dd46ab5SKacheong Poon * CDDL HEADER END 205dd46ab5SKacheong Poon */ 215dd46ab5SKacheong Poon 225dd46ab5SKacheong Poon /* 235dd46ab5SKacheong Poon * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 245dd46ab5SKacheong Poon */ 255dd46ab5SKacheong Poon 265dd46ab5SKacheong Poon #include <sys/types.h> 275dd46ab5SKacheong Poon #include <sys/tihdr.h> 285dd46ab5SKacheong Poon #include <sys/policy.h> 295dd46ab5SKacheong Poon #include <sys/tsol/tnet.h> 305dd46ab5SKacheong Poon 315dd46ab5SKacheong Poon #include <inet/common.h> 325dd46ab5SKacheong Poon #include <inet/kstatcom.h> 335dd46ab5SKacheong Poon #include <inet/snmpcom.h> 345dd46ab5SKacheong Poon #include <inet/mib2.h> 355dd46ab5SKacheong Poon #include <inet/optcom.h> 365dd46ab5SKacheong Poon #include <inet/snmpcom.h> 375dd46ab5SKacheong Poon #include <inet/kstatcom.h> 385dd46ab5SKacheong Poon #include <inet/udp_impl.h> 395dd46ab5SKacheong Poon 405dd46ab5SKacheong Poon static int udp_kstat_update(kstat_t *, int); 415dd46ab5SKacheong Poon static int udp_kstat2_update(kstat_t *, int); 425dd46ab5SKacheong Poon static void udp_sum_mib(udp_stack_t *, mib2_udp_t *); 435dd46ab5SKacheong Poon static void udp_clr_stats(udp_stat_t *); 445dd46ab5SKacheong Poon static void udp_add_stats(udp_stat_counter_t *, udp_stat_t *); 455dd46ab5SKacheong Poon static void udp_add_mib(mib2_udp_t *, mib2_udp_t *); 465dd46ab5SKacheong Poon /* 475dd46ab5SKacheong Poon * return SNMP stuff in buffer in mpdata. We don't hold any lock and report 485dd46ab5SKacheong Poon * information that can be changing beneath us. 495dd46ab5SKacheong Poon */ 505dd46ab5SKacheong Poon mblk_t * 51*6f773e29SBaban Kenkre udp_snmp_get(queue_t *q, mblk_t *mpctl, boolean_t legacy_req) 525dd46ab5SKacheong Poon { 535dd46ab5SKacheong Poon mblk_t *mpdata; 545dd46ab5SKacheong Poon mblk_t *mp_conn_ctl; 555dd46ab5SKacheong Poon mblk_t *mp_attr_ctl; 565dd46ab5SKacheong Poon mblk_t *mp6_conn_ctl; 575dd46ab5SKacheong Poon mblk_t *mp6_attr_ctl; 585dd46ab5SKacheong Poon mblk_t *mp_conn_tail; 595dd46ab5SKacheong Poon mblk_t *mp_attr_tail; 605dd46ab5SKacheong Poon mblk_t *mp6_conn_tail; 615dd46ab5SKacheong Poon mblk_t *mp6_attr_tail; 625dd46ab5SKacheong Poon struct opthdr *optp; 635dd46ab5SKacheong Poon mib2_udpEntry_t ude; 645dd46ab5SKacheong Poon mib2_udp6Entry_t ude6; 655dd46ab5SKacheong Poon mib2_transportMLPEntry_t mlp; 665dd46ab5SKacheong Poon int state; 675dd46ab5SKacheong Poon zoneid_t zoneid; 685dd46ab5SKacheong Poon int i; 695dd46ab5SKacheong Poon connf_t *connfp; 705dd46ab5SKacheong Poon conn_t *connp = Q_TO_CONN(q); 715dd46ab5SKacheong Poon int v4_conn_idx; 725dd46ab5SKacheong Poon int v6_conn_idx; 735dd46ab5SKacheong Poon boolean_t needattr; 745dd46ab5SKacheong Poon udp_t *udp; 755dd46ab5SKacheong Poon ip_stack_t *ipst = connp->conn_netstack->netstack_ip; 765dd46ab5SKacheong Poon udp_stack_t *us = connp->conn_netstack->netstack_udp; 775dd46ab5SKacheong Poon mblk_t *mp2ctl; 785dd46ab5SKacheong Poon mib2_udp_t udp_mib; 79*6f773e29SBaban Kenkre size_t udp_mib_size, ude_size, ude6_size; 80*6f773e29SBaban Kenkre 815dd46ab5SKacheong Poon 825dd46ab5SKacheong Poon /* 835dd46ab5SKacheong Poon * make a copy of the original message 845dd46ab5SKacheong Poon */ 855dd46ab5SKacheong Poon mp2ctl = copymsg(mpctl); 865dd46ab5SKacheong Poon 875dd46ab5SKacheong Poon mp_conn_ctl = mp_attr_ctl = mp6_conn_ctl = NULL; 885dd46ab5SKacheong Poon if (mpctl == NULL || 895dd46ab5SKacheong Poon (mpdata = mpctl->b_cont) == NULL || 905dd46ab5SKacheong Poon (mp_conn_ctl = copymsg(mpctl)) == NULL || 915dd46ab5SKacheong Poon (mp_attr_ctl = copymsg(mpctl)) == NULL || 925dd46ab5SKacheong Poon (mp6_conn_ctl = copymsg(mpctl)) == NULL || 935dd46ab5SKacheong Poon (mp6_attr_ctl = copymsg(mpctl)) == NULL) { 945dd46ab5SKacheong Poon freemsg(mp_conn_ctl); 955dd46ab5SKacheong Poon freemsg(mp_attr_ctl); 965dd46ab5SKacheong Poon freemsg(mp6_conn_ctl); 975dd46ab5SKacheong Poon freemsg(mpctl); 985dd46ab5SKacheong Poon freemsg(mp2ctl); 995dd46ab5SKacheong Poon return (0); 1005dd46ab5SKacheong Poon } 1015dd46ab5SKacheong Poon 1025dd46ab5SKacheong Poon zoneid = connp->conn_zoneid; 1035dd46ab5SKacheong Poon 104*6f773e29SBaban Kenkre if (legacy_req) { 105*6f773e29SBaban Kenkre udp_mib_size = LEGACY_MIB_SIZE(&udp_mib, mib2_udp_t); 106*6f773e29SBaban Kenkre ude_size = LEGACY_MIB_SIZE(&ude, mib2_udpEntry_t); 107*6f773e29SBaban Kenkre ude6_size = LEGACY_MIB_SIZE(&ude6, mib2_udp6Entry_t); 108*6f773e29SBaban Kenkre } else { 109*6f773e29SBaban Kenkre udp_mib_size = sizeof (mib2_udp_t); 110*6f773e29SBaban Kenkre ude_size = sizeof (mib2_udpEntry_t); 111*6f773e29SBaban Kenkre ude6_size = sizeof (mib2_udp6Entry_t); 112*6f773e29SBaban Kenkre } 113*6f773e29SBaban Kenkre 1145dd46ab5SKacheong Poon bzero(&udp_mib, sizeof (udp_mib)); 1155dd46ab5SKacheong Poon /* fixed length structure for IPv4 and IPv6 counters */ 116*6f773e29SBaban Kenkre SET_MIB(udp_mib.udpEntrySize, ude_size); 117*6f773e29SBaban Kenkre SET_MIB(udp_mib.udp6EntrySize, ude6_size); 1185dd46ab5SKacheong Poon 1195dd46ab5SKacheong Poon udp_sum_mib(us, &udp_mib); 1205dd46ab5SKacheong Poon 1215dd46ab5SKacheong Poon /* 1225dd46ab5SKacheong Poon * Synchronize 32- and 64-bit counters. Note that udpInDatagrams and 1235dd46ab5SKacheong Poon * udpOutDatagrams are not updated anywhere in UDP. The new 64 bits 1245dd46ab5SKacheong Poon * counters are used. Hence the old counters' values in us_sc_mib 1255dd46ab5SKacheong Poon * are always 0. 1265dd46ab5SKacheong Poon */ 1275dd46ab5SKacheong Poon SYNC32_MIB(&udp_mib, udpInDatagrams, udpHCInDatagrams); 1285dd46ab5SKacheong Poon SYNC32_MIB(&udp_mib, udpOutDatagrams, udpHCOutDatagrams); 1295dd46ab5SKacheong Poon 1305dd46ab5SKacheong Poon optp = (struct opthdr *)&mpctl->b_rptr[sizeof (struct T_optmgmt_ack)]; 1315dd46ab5SKacheong Poon optp->level = MIB2_UDP; 1325dd46ab5SKacheong Poon optp->name = 0; 133*6f773e29SBaban Kenkre (void) snmp_append_data(mpdata, (char *)&udp_mib, udp_mib_size); 1345dd46ab5SKacheong Poon optp->len = msgdsize(mpdata); 1355dd46ab5SKacheong Poon qreply(q, mpctl); 1365dd46ab5SKacheong Poon 1375dd46ab5SKacheong Poon mp_conn_tail = mp_attr_tail = mp6_conn_tail = mp6_attr_tail = NULL; 1385dd46ab5SKacheong Poon v4_conn_idx = v6_conn_idx = 0; 1395dd46ab5SKacheong Poon 1405dd46ab5SKacheong Poon for (i = 0; i < CONN_G_HASH_SIZE; i++) { 1415dd46ab5SKacheong Poon connfp = &ipst->ips_ipcl_globalhash_fanout[i]; 1425dd46ab5SKacheong Poon connp = NULL; 1435dd46ab5SKacheong Poon 1445dd46ab5SKacheong Poon while ((connp = ipcl_get_next_conn(connfp, connp, 1455dd46ab5SKacheong Poon IPCL_UDPCONN))) { 1465dd46ab5SKacheong Poon udp = connp->conn_udp; 1475dd46ab5SKacheong Poon if (zoneid != connp->conn_zoneid) 1485dd46ab5SKacheong Poon continue; 1495dd46ab5SKacheong Poon 1505dd46ab5SKacheong Poon /* 1515dd46ab5SKacheong Poon * Note that the port numbers are sent in 1525dd46ab5SKacheong Poon * host byte order 1535dd46ab5SKacheong Poon */ 1545dd46ab5SKacheong Poon 1555dd46ab5SKacheong Poon if (udp->udp_state == TS_UNBND) 1565dd46ab5SKacheong Poon state = MIB2_UDP_unbound; 1575dd46ab5SKacheong Poon else if (udp->udp_state == TS_IDLE) 1585dd46ab5SKacheong Poon state = MIB2_UDP_idle; 1595dd46ab5SKacheong Poon else if (udp->udp_state == TS_DATA_XFER) 1605dd46ab5SKacheong Poon state = MIB2_UDP_connected; 1615dd46ab5SKacheong Poon else 1625dd46ab5SKacheong Poon state = MIB2_UDP_unknown; 1635dd46ab5SKacheong Poon 1645dd46ab5SKacheong Poon needattr = B_FALSE; 1655dd46ab5SKacheong Poon bzero(&mlp, sizeof (mlp)); 1665dd46ab5SKacheong Poon if (connp->conn_mlp_type != mlptSingle) { 1675dd46ab5SKacheong Poon if (connp->conn_mlp_type == mlptShared || 1685dd46ab5SKacheong Poon connp->conn_mlp_type == mlptBoth) 1695dd46ab5SKacheong Poon mlp.tme_flags |= MIB2_TMEF_SHARED; 1705dd46ab5SKacheong Poon if (connp->conn_mlp_type == mlptPrivate || 1715dd46ab5SKacheong Poon connp->conn_mlp_type == mlptBoth) 1725dd46ab5SKacheong Poon mlp.tme_flags |= MIB2_TMEF_PRIVATE; 1735dd46ab5SKacheong Poon needattr = B_TRUE; 1745dd46ab5SKacheong Poon } 1755dd46ab5SKacheong Poon if (connp->conn_anon_mlp) { 1765dd46ab5SKacheong Poon mlp.tme_flags |= MIB2_TMEF_ANONMLP; 1775dd46ab5SKacheong Poon needattr = B_TRUE; 1785dd46ab5SKacheong Poon } 1795dd46ab5SKacheong Poon switch (connp->conn_mac_mode) { 1805dd46ab5SKacheong Poon case CONN_MAC_DEFAULT: 1815dd46ab5SKacheong Poon break; 1825dd46ab5SKacheong Poon case CONN_MAC_AWARE: 1835dd46ab5SKacheong Poon mlp.tme_flags |= MIB2_TMEF_MACEXEMPT; 1845dd46ab5SKacheong Poon needattr = B_TRUE; 1855dd46ab5SKacheong Poon break; 1865dd46ab5SKacheong Poon case CONN_MAC_IMPLICIT: 1875dd46ab5SKacheong Poon mlp.tme_flags |= MIB2_TMEF_MACIMPLICIT; 1885dd46ab5SKacheong Poon needattr = B_TRUE; 1895dd46ab5SKacheong Poon break; 1905dd46ab5SKacheong Poon } 1915dd46ab5SKacheong Poon mutex_enter(&connp->conn_lock); 1925dd46ab5SKacheong Poon if (udp->udp_state == TS_DATA_XFER && 1935dd46ab5SKacheong Poon connp->conn_ixa->ixa_tsl != NULL) { 1945dd46ab5SKacheong Poon ts_label_t *tsl; 1955dd46ab5SKacheong Poon 1965dd46ab5SKacheong Poon tsl = connp->conn_ixa->ixa_tsl; 1975dd46ab5SKacheong Poon mlp.tme_flags |= MIB2_TMEF_IS_LABELED; 1985dd46ab5SKacheong Poon mlp.tme_doi = label2doi(tsl); 1995dd46ab5SKacheong Poon mlp.tme_label = *label2bslabel(tsl); 2005dd46ab5SKacheong Poon needattr = B_TRUE; 2015dd46ab5SKacheong Poon } 2025dd46ab5SKacheong Poon mutex_exit(&connp->conn_lock); 2035dd46ab5SKacheong Poon 2045dd46ab5SKacheong Poon /* 2055dd46ab5SKacheong Poon * Create an IPv4 table entry for IPv4 entries and also 2065dd46ab5SKacheong Poon * any IPv6 entries which are bound to in6addr_any 2075dd46ab5SKacheong Poon * (i.e. anything a IPv4 peer could connect/send to). 2085dd46ab5SKacheong Poon */ 2095dd46ab5SKacheong Poon if (connp->conn_ipversion == IPV4_VERSION || 2105dd46ab5SKacheong Poon (udp->udp_state <= TS_IDLE && 2115dd46ab5SKacheong Poon IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6))) { 2125dd46ab5SKacheong Poon ude.udpEntryInfo.ue_state = state; 2135dd46ab5SKacheong Poon /* 2145dd46ab5SKacheong Poon * If in6addr_any this will set it to 2155dd46ab5SKacheong Poon * INADDR_ANY 2165dd46ab5SKacheong Poon */ 2175dd46ab5SKacheong Poon ude.udpLocalAddress = connp->conn_laddr_v4; 2185dd46ab5SKacheong Poon ude.udpLocalPort = ntohs(connp->conn_lport); 2195dd46ab5SKacheong Poon if (udp->udp_state == TS_DATA_XFER) { 2205dd46ab5SKacheong Poon /* 2215dd46ab5SKacheong Poon * Can potentially get here for 2225dd46ab5SKacheong Poon * v6 socket if another process 2235dd46ab5SKacheong Poon * (say, ping) has just done a 2245dd46ab5SKacheong Poon * sendto(), changing the state 2255dd46ab5SKacheong Poon * from the TS_IDLE above to 2265dd46ab5SKacheong Poon * TS_DATA_XFER by the time we hit 2275dd46ab5SKacheong Poon * this part of the code. 2285dd46ab5SKacheong Poon */ 2295dd46ab5SKacheong Poon ude.udpEntryInfo.ue_RemoteAddress = 2305dd46ab5SKacheong Poon connp->conn_faddr_v4; 2315dd46ab5SKacheong Poon ude.udpEntryInfo.ue_RemotePort = 2325dd46ab5SKacheong Poon ntohs(connp->conn_fport); 2335dd46ab5SKacheong Poon } else { 2345dd46ab5SKacheong Poon ude.udpEntryInfo.ue_RemoteAddress = 0; 2355dd46ab5SKacheong Poon ude.udpEntryInfo.ue_RemotePort = 0; 2365dd46ab5SKacheong Poon } 2375dd46ab5SKacheong Poon 2385dd46ab5SKacheong Poon /* 2395dd46ab5SKacheong Poon * We make the assumption that all udp_t 2405dd46ab5SKacheong Poon * structs will be created within an address 2415dd46ab5SKacheong Poon * region no larger than 32-bits. 2425dd46ab5SKacheong Poon */ 2435dd46ab5SKacheong Poon ude.udpInstance = (uint32_t)(uintptr_t)udp; 2445dd46ab5SKacheong Poon ude.udpCreationProcess = 2455dd46ab5SKacheong Poon (connp->conn_cpid < 0) ? 2465dd46ab5SKacheong Poon MIB2_UNKNOWN_PROCESS : 2475dd46ab5SKacheong Poon connp->conn_cpid; 2485dd46ab5SKacheong Poon ude.udpCreationTime = connp->conn_open_time; 2495dd46ab5SKacheong Poon 2505dd46ab5SKacheong Poon (void) snmp_append_data2(mp_conn_ctl->b_cont, 251*6f773e29SBaban Kenkre &mp_conn_tail, (char *)&ude, ude_size); 2525dd46ab5SKacheong Poon mlp.tme_connidx = v4_conn_idx++; 2535dd46ab5SKacheong Poon if (needattr) 2545dd46ab5SKacheong Poon (void) snmp_append_data2( 2555dd46ab5SKacheong Poon mp_attr_ctl->b_cont, &mp_attr_tail, 2565dd46ab5SKacheong Poon (char *)&mlp, sizeof (mlp)); 2575dd46ab5SKacheong Poon } 2585dd46ab5SKacheong Poon if (connp->conn_ipversion == IPV6_VERSION) { 2595dd46ab5SKacheong Poon ude6.udp6EntryInfo.ue_state = state; 2605dd46ab5SKacheong Poon ude6.udp6LocalAddress = connp->conn_laddr_v6; 2615dd46ab5SKacheong Poon ude6.udp6LocalPort = ntohs(connp->conn_lport); 2625dd46ab5SKacheong Poon mutex_enter(&connp->conn_lock); 2635dd46ab5SKacheong Poon if (connp->conn_ixa->ixa_flags & 2645dd46ab5SKacheong Poon IXAF_SCOPEID_SET) { 2655dd46ab5SKacheong Poon ude6.udp6IfIndex = 2665dd46ab5SKacheong Poon connp->conn_ixa->ixa_scopeid; 2675dd46ab5SKacheong Poon } else { 2685dd46ab5SKacheong Poon ude6.udp6IfIndex = connp->conn_bound_if; 2695dd46ab5SKacheong Poon } 2705dd46ab5SKacheong Poon mutex_exit(&connp->conn_lock); 2715dd46ab5SKacheong Poon if (udp->udp_state == TS_DATA_XFER) { 2725dd46ab5SKacheong Poon ude6.udp6EntryInfo.ue_RemoteAddress = 2735dd46ab5SKacheong Poon connp->conn_faddr_v6; 2745dd46ab5SKacheong Poon ude6.udp6EntryInfo.ue_RemotePort = 2755dd46ab5SKacheong Poon ntohs(connp->conn_fport); 2765dd46ab5SKacheong Poon } else { 2775dd46ab5SKacheong Poon ude6.udp6EntryInfo.ue_RemoteAddress = 2785dd46ab5SKacheong Poon sin6_null.sin6_addr; 2795dd46ab5SKacheong Poon ude6.udp6EntryInfo.ue_RemotePort = 0; 2805dd46ab5SKacheong Poon } 2815dd46ab5SKacheong Poon /* 2825dd46ab5SKacheong Poon * We make the assumption that all udp_t 2835dd46ab5SKacheong Poon * structs will be created within an address 2845dd46ab5SKacheong Poon * region no larger than 32-bits. 2855dd46ab5SKacheong Poon */ 2865dd46ab5SKacheong Poon ude6.udp6Instance = (uint32_t)(uintptr_t)udp; 2875dd46ab5SKacheong Poon ude6.udp6CreationProcess = 2885dd46ab5SKacheong Poon (connp->conn_cpid < 0) ? 2895dd46ab5SKacheong Poon MIB2_UNKNOWN_PROCESS : 2905dd46ab5SKacheong Poon connp->conn_cpid; 2915dd46ab5SKacheong Poon ude6.udp6CreationTime = connp->conn_open_time; 2925dd46ab5SKacheong Poon 2935dd46ab5SKacheong Poon (void) snmp_append_data2(mp6_conn_ctl->b_cont, 294*6f773e29SBaban Kenkre &mp6_conn_tail, (char *)&ude6, ude6_size); 2955dd46ab5SKacheong Poon mlp.tme_connidx = v6_conn_idx++; 2965dd46ab5SKacheong Poon if (needattr) 2975dd46ab5SKacheong Poon (void) snmp_append_data2( 2985dd46ab5SKacheong Poon mp6_attr_ctl->b_cont, 2995dd46ab5SKacheong Poon &mp6_attr_tail, (char *)&mlp, 3005dd46ab5SKacheong Poon sizeof (mlp)); 3015dd46ab5SKacheong Poon } 3025dd46ab5SKacheong Poon } 3035dd46ab5SKacheong Poon } 3045dd46ab5SKacheong Poon 3055dd46ab5SKacheong Poon /* IPv4 UDP endpoints */ 3065dd46ab5SKacheong Poon optp = (struct opthdr *)&mp_conn_ctl->b_rptr[ 3075dd46ab5SKacheong Poon sizeof (struct T_optmgmt_ack)]; 3085dd46ab5SKacheong Poon optp->level = MIB2_UDP; 3095dd46ab5SKacheong Poon optp->name = MIB2_UDP_ENTRY; 3105dd46ab5SKacheong Poon optp->len = msgdsize(mp_conn_ctl->b_cont); 3115dd46ab5SKacheong Poon qreply(q, mp_conn_ctl); 3125dd46ab5SKacheong Poon 3135dd46ab5SKacheong Poon /* table of MLP attributes... */ 3145dd46ab5SKacheong Poon optp = (struct opthdr *)&mp_attr_ctl->b_rptr[ 3155dd46ab5SKacheong Poon sizeof (struct T_optmgmt_ack)]; 3165dd46ab5SKacheong Poon optp->level = MIB2_UDP; 3175dd46ab5SKacheong Poon optp->name = EXPER_XPORT_MLP; 3185dd46ab5SKacheong Poon optp->len = msgdsize(mp_attr_ctl->b_cont); 3195dd46ab5SKacheong Poon if (optp->len == 0) 3205dd46ab5SKacheong Poon freemsg(mp_attr_ctl); 3215dd46ab5SKacheong Poon else 3225dd46ab5SKacheong Poon qreply(q, mp_attr_ctl); 3235dd46ab5SKacheong Poon 3245dd46ab5SKacheong Poon /* IPv6 UDP endpoints */ 3255dd46ab5SKacheong Poon optp = (struct opthdr *)&mp6_conn_ctl->b_rptr[ 3265dd46ab5SKacheong Poon sizeof (struct T_optmgmt_ack)]; 3275dd46ab5SKacheong Poon optp->level = MIB2_UDP6; 3285dd46ab5SKacheong Poon optp->name = MIB2_UDP6_ENTRY; 3295dd46ab5SKacheong Poon optp->len = msgdsize(mp6_conn_ctl->b_cont); 3305dd46ab5SKacheong Poon qreply(q, mp6_conn_ctl); 3315dd46ab5SKacheong Poon 3325dd46ab5SKacheong Poon /* table of MLP attributes... */ 3335dd46ab5SKacheong Poon optp = (struct opthdr *)&mp6_attr_ctl->b_rptr[ 3345dd46ab5SKacheong Poon sizeof (struct T_optmgmt_ack)]; 3355dd46ab5SKacheong Poon optp->level = MIB2_UDP6; 3365dd46ab5SKacheong Poon optp->name = EXPER_XPORT_MLP; 3375dd46ab5SKacheong Poon optp->len = msgdsize(mp6_attr_ctl->b_cont); 3385dd46ab5SKacheong Poon if (optp->len == 0) 3395dd46ab5SKacheong Poon freemsg(mp6_attr_ctl); 3405dd46ab5SKacheong Poon else 3415dd46ab5SKacheong Poon qreply(q, mp6_attr_ctl); 3425dd46ab5SKacheong Poon 3435dd46ab5SKacheong Poon return (mp2ctl); 3445dd46ab5SKacheong Poon } 3455dd46ab5SKacheong Poon 3465dd46ab5SKacheong Poon /* 3475dd46ab5SKacheong Poon * Return 0 if invalid set request, 1 otherwise, including non-udp requests. 3485dd46ab5SKacheong Poon * NOTE: Per MIB-II, UDP has no writable data. 3495dd46ab5SKacheong Poon * TODO: If this ever actually tries to set anything, it needs to be 3505dd46ab5SKacheong Poon * to do the appropriate locking. 3515dd46ab5SKacheong Poon */ 3525dd46ab5SKacheong Poon /* ARGSUSED */ 3535dd46ab5SKacheong Poon int 3545dd46ab5SKacheong Poon udp_snmp_set(queue_t *q, t_scalar_t level, t_scalar_t name, 3555dd46ab5SKacheong Poon uchar_t *ptr, int len) 3565dd46ab5SKacheong Poon { 3575dd46ab5SKacheong Poon switch (level) { 3585dd46ab5SKacheong Poon case MIB2_UDP: 3595dd46ab5SKacheong Poon return (0); 3605dd46ab5SKacheong Poon default: 3615dd46ab5SKacheong Poon return (1); 3625dd46ab5SKacheong Poon } 3635dd46ab5SKacheong Poon } 3645dd46ab5SKacheong Poon 3655dd46ab5SKacheong Poon void 3665dd46ab5SKacheong Poon udp_kstat_fini(netstackid_t stackid, kstat_t *ksp) 3675dd46ab5SKacheong Poon { 3685dd46ab5SKacheong Poon if (ksp != NULL) { 3695dd46ab5SKacheong Poon ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private); 3705dd46ab5SKacheong Poon kstat_delete_netstack(ksp, stackid); 3715dd46ab5SKacheong Poon } 3725dd46ab5SKacheong Poon } 3735dd46ab5SKacheong Poon 3745dd46ab5SKacheong Poon /* 3755dd46ab5SKacheong Poon * To add stats from one mib2_udp_t to another. Static fields are not added. 3765dd46ab5SKacheong Poon * The caller should set them up propertly. 3775dd46ab5SKacheong Poon */ 3785dd46ab5SKacheong Poon static void 3795dd46ab5SKacheong Poon udp_add_mib(mib2_udp_t *from, mib2_udp_t *to) 3805dd46ab5SKacheong Poon { 3815dd46ab5SKacheong Poon to->udpHCInDatagrams += from->udpHCInDatagrams; 3825dd46ab5SKacheong Poon to->udpInErrors += from->udpInErrors; 3835dd46ab5SKacheong Poon to->udpHCOutDatagrams += from->udpHCOutDatagrams; 3845dd46ab5SKacheong Poon to->udpOutErrors += from->udpOutErrors; 3855dd46ab5SKacheong Poon } 3865dd46ab5SKacheong Poon 3875dd46ab5SKacheong Poon 3885dd46ab5SKacheong Poon void * 3895dd46ab5SKacheong Poon udp_kstat2_init(netstackid_t stackid) 3905dd46ab5SKacheong Poon { 3915dd46ab5SKacheong Poon kstat_t *ksp; 3925dd46ab5SKacheong Poon 3935dd46ab5SKacheong Poon udp_stat_t template = { 3945dd46ab5SKacheong Poon { "udp_sock_fallback", KSTAT_DATA_UINT64 }, 3955dd46ab5SKacheong Poon { "udp_out_opt", KSTAT_DATA_UINT64 }, 3965dd46ab5SKacheong Poon { "udp_out_err_notconn", KSTAT_DATA_UINT64 }, 3975dd46ab5SKacheong Poon { "udp_out_err_output", KSTAT_DATA_UINT64 }, 3985dd46ab5SKacheong Poon { "udp_out_err_tudr", KSTAT_DATA_UINT64 }, 3995dd46ab5SKacheong Poon #ifdef DEBUG 4005dd46ab5SKacheong Poon { "udp_data_conn", KSTAT_DATA_UINT64 }, 4015dd46ab5SKacheong Poon { "udp_data_notconn", KSTAT_DATA_UINT64 }, 4025dd46ab5SKacheong Poon { "udp_out_lastdst", KSTAT_DATA_UINT64 }, 4035dd46ab5SKacheong Poon { "udp_out_diffdst", KSTAT_DATA_UINT64 }, 4045dd46ab5SKacheong Poon { "udp_out_ipv6", KSTAT_DATA_UINT64 }, 4055dd46ab5SKacheong Poon { "udp_out_mapped", KSTAT_DATA_UINT64 }, 4065dd46ab5SKacheong Poon { "udp_out_ipv4", KSTAT_DATA_UINT64 }, 4075dd46ab5SKacheong Poon #endif 4085dd46ab5SKacheong Poon }; 4095dd46ab5SKacheong Poon 4105dd46ab5SKacheong Poon ksp = kstat_create_netstack(UDP_MOD_NAME, 0, "udpstat", "net", 4115dd46ab5SKacheong Poon KSTAT_TYPE_NAMED, sizeof (template) / sizeof (kstat_named_t), 4125dd46ab5SKacheong Poon 0, stackid); 4135dd46ab5SKacheong Poon 4145dd46ab5SKacheong Poon if (ksp == NULL) 4155dd46ab5SKacheong Poon return (NULL); 4165dd46ab5SKacheong Poon 4175dd46ab5SKacheong Poon bcopy(&template, ksp->ks_data, sizeof (template)); 4185dd46ab5SKacheong Poon ksp->ks_update = udp_kstat2_update; 4195dd46ab5SKacheong Poon ksp->ks_private = (void *)(uintptr_t)stackid; 4205dd46ab5SKacheong Poon 4215dd46ab5SKacheong Poon kstat_install(ksp); 4225dd46ab5SKacheong Poon return (ksp); 4235dd46ab5SKacheong Poon } 4245dd46ab5SKacheong Poon 4255dd46ab5SKacheong Poon void 4265dd46ab5SKacheong Poon udp_kstat2_fini(netstackid_t stackid, kstat_t *ksp) 4275dd46ab5SKacheong Poon { 4285dd46ab5SKacheong Poon if (ksp != NULL) { 4295dd46ab5SKacheong Poon ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private); 4305dd46ab5SKacheong Poon kstat_delete_netstack(ksp, stackid); 4315dd46ab5SKacheong Poon } 4325dd46ab5SKacheong Poon } 4335dd46ab5SKacheong Poon 4345dd46ab5SKacheong Poon /* 4355dd46ab5SKacheong Poon * To copy counters from the per CPU udpp_stat_counter_t to the stack 4365dd46ab5SKacheong Poon * udp_stat_t. 4375dd46ab5SKacheong Poon */ 4385dd46ab5SKacheong Poon static void 4395dd46ab5SKacheong Poon udp_add_stats(udp_stat_counter_t *from, udp_stat_t *to) 4405dd46ab5SKacheong Poon { 4415dd46ab5SKacheong Poon to->udp_sock_fallback.value.ui64 += from->udp_sock_fallback; 4425dd46ab5SKacheong Poon to->udp_out_opt.value.ui64 += from->udp_out_opt; 4435dd46ab5SKacheong Poon to->udp_out_err_notconn.value.ui64 += from->udp_out_err_notconn; 4445dd46ab5SKacheong Poon to->udp_out_err_output.value.ui64 += from->udp_out_err_output; 4455dd46ab5SKacheong Poon to->udp_out_err_tudr.value.ui64 += from->udp_out_err_tudr; 4465dd46ab5SKacheong Poon #ifdef DEBUG 4475dd46ab5SKacheong Poon to->udp_data_conn.value.ui64 += from->udp_data_conn; 4485dd46ab5SKacheong Poon to->udp_data_notconn.value.ui64 += from->udp_data_notconn; 4495dd46ab5SKacheong Poon to->udp_out_lastdst.value.ui64 += from->udp_out_lastdst; 4505dd46ab5SKacheong Poon to->udp_out_diffdst.value.ui64 += from->udp_out_diffdst; 4515dd46ab5SKacheong Poon to->udp_out_ipv6.value.ui64 += from->udp_out_ipv6; 4525dd46ab5SKacheong Poon to->udp_out_mapped.value.ui64 += from->udp_out_mapped; 4535dd46ab5SKacheong Poon to->udp_out_ipv4.value.ui64 += from->udp_out_ipv4; 4545dd46ab5SKacheong Poon #endif 4555dd46ab5SKacheong Poon } 4565dd46ab5SKacheong Poon 4575dd46ab5SKacheong Poon /* 4585dd46ab5SKacheong Poon * To set all udp_stat_t counters to 0. 4595dd46ab5SKacheong Poon */ 4605dd46ab5SKacheong Poon static void 4615dd46ab5SKacheong Poon udp_clr_stats(udp_stat_t *stats) 4625dd46ab5SKacheong Poon { 4635dd46ab5SKacheong Poon stats->udp_sock_fallback.value.ui64 = 0; 4645dd46ab5SKacheong Poon stats->udp_out_opt.value.ui64 = 0; 4655dd46ab5SKacheong Poon stats->udp_out_err_notconn.value.ui64 = 0; 4665dd46ab5SKacheong Poon stats->udp_out_err_output.value.ui64 = 0; 4675dd46ab5SKacheong Poon stats->udp_out_err_tudr.value.ui64 = 0; 4685dd46ab5SKacheong Poon #ifdef DEBUG 4695dd46ab5SKacheong Poon stats->udp_data_conn.value.ui64 = 0; 4705dd46ab5SKacheong Poon stats->udp_data_notconn.value.ui64 = 0; 4715dd46ab5SKacheong Poon stats->udp_out_lastdst.value.ui64 = 0; 4725dd46ab5SKacheong Poon stats->udp_out_diffdst.value.ui64 = 0; 4735dd46ab5SKacheong Poon stats->udp_out_ipv6.value.ui64 = 0; 4745dd46ab5SKacheong Poon stats->udp_out_mapped.value.ui64 = 0; 4755dd46ab5SKacheong Poon stats->udp_out_ipv4.value.ui64 = 0; 4765dd46ab5SKacheong Poon #endif 4775dd46ab5SKacheong Poon } 4785dd46ab5SKacheong Poon 4795dd46ab5SKacheong Poon int 4805dd46ab5SKacheong Poon udp_kstat2_update(kstat_t *kp, int rw) 4815dd46ab5SKacheong Poon { 4825dd46ab5SKacheong Poon udp_stat_t *stats; 4835dd46ab5SKacheong Poon netstackid_t stackid = (netstackid_t)(uintptr_t)kp->ks_private; 4845dd46ab5SKacheong Poon netstack_t *ns; 4855dd46ab5SKacheong Poon udp_stack_t *us; 4865dd46ab5SKacheong Poon int i; 4875dd46ab5SKacheong Poon int cnt; 4885dd46ab5SKacheong Poon 4895dd46ab5SKacheong Poon if (rw == KSTAT_WRITE) 4905dd46ab5SKacheong Poon return (EACCES); 4915dd46ab5SKacheong Poon 4925dd46ab5SKacheong Poon ns = netstack_find_by_stackid(stackid); 4935dd46ab5SKacheong Poon if (ns == NULL) 4945dd46ab5SKacheong Poon return (-1); 4955dd46ab5SKacheong Poon us = ns->netstack_udp; 4965dd46ab5SKacheong Poon if (us == NULL) { 4975dd46ab5SKacheong Poon netstack_rele(ns); 4985dd46ab5SKacheong Poon return (-1); 4995dd46ab5SKacheong Poon } 5005dd46ab5SKacheong Poon stats = (udp_stat_t *)kp->ks_data; 5015dd46ab5SKacheong Poon udp_clr_stats(stats); 5025dd46ab5SKacheong Poon 5035dd46ab5SKacheong Poon cnt = us->us_sc_cnt; 5045dd46ab5SKacheong Poon for (i = 0; i < cnt; i++) 5055dd46ab5SKacheong Poon udp_add_stats(&us->us_sc[i]->udp_sc_stats, stats); 5065dd46ab5SKacheong Poon 5075dd46ab5SKacheong Poon netstack_rele(ns); 5085dd46ab5SKacheong Poon return (0); 5095dd46ab5SKacheong Poon } 5105dd46ab5SKacheong Poon 5115dd46ab5SKacheong Poon void * 5125dd46ab5SKacheong Poon udp_kstat_init(netstackid_t stackid) 5135dd46ab5SKacheong Poon { 5145dd46ab5SKacheong Poon kstat_t *ksp; 5155dd46ab5SKacheong Poon 5165dd46ab5SKacheong Poon udp_named_kstat_t template = { 5175dd46ab5SKacheong Poon { "inDatagrams", KSTAT_DATA_UINT64, 0 }, 5185dd46ab5SKacheong Poon { "inErrors", KSTAT_DATA_UINT32, 0 }, 5195dd46ab5SKacheong Poon { "outDatagrams", KSTAT_DATA_UINT64, 0 }, 5205dd46ab5SKacheong Poon { "entrySize", KSTAT_DATA_INT32, 0 }, 5215dd46ab5SKacheong Poon { "entry6Size", KSTAT_DATA_INT32, 0 }, 5225dd46ab5SKacheong Poon { "outErrors", KSTAT_DATA_UINT32, 0 }, 5235dd46ab5SKacheong Poon }; 5245dd46ab5SKacheong Poon 5255dd46ab5SKacheong Poon ksp = kstat_create_netstack(UDP_MOD_NAME, 0, UDP_MOD_NAME, "mib2", 5265dd46ab5SKacheong Poon KSTAT_TYPE_NAMED, NUM_OF_FIELDS(udp_named_kstat_t), 0, stackid); 5275dd46ab5SKacheong Poon 5285dd46ab5SKacheong Poon if (ksp == NULL) 5295dd46ab5SKacheong Poon return (NULL); 5305dd46ab5SKacheong Poon 5315dd46ab5SKacheong Poon template.entrySize.value.ui32 = sizeof (mib2_udpEntry_t); 5325dd46ab5SKacheong Poon template.entry6Size.value.ui32 = sizeof (mib2_udp6Entry_t); 5335dd46ab5SKacheong Poon 5345dd46ab5SKacheong Poon bcopy(&template, ksp->ks_data, sizeof (template)); 5355dd46ab5SKacheong Poon ksp->ks_update = udp_kstat_update; 5365dd46ab5SKacheong Poon ksp->ks_private = (void *)(uintptr_t)stackid; 5375dd46ab5SKacheong Poon 5385dd46ab5SKacheong Poon kstat_install(ksp); 5395dd46ab5SKacheong Poon return (ksp); 5405dd46ab5SKacheong Poon } 5415dd46ab5SKacheong Poon 5425dd46ab5SKacheong Poon /* 5435dd46ab5SKacheong Poon * To sum up all MIB2 stats for a udp_stack_t from all per CPU stats. The 5445dd46ab5SKacheong Poon * caller should initialize the target mib2_udp_t properly as this function 5455dd46ab5SKacheong Poon * just adds up all the per CPU stats. 5465dd46ab5SKacheong Poon */ 5475dd46ab5SKacheong Poon static void 5485dd46ab5SKacheong Poon udp_sum_mib(udp_stack_t *us, mib2_udp_t *udp_mib) 5495dd46ab5SKacheong Poon { 5505dd46ab5SKacheong Poon int i; 5515dd46ab5SKacheong Poon int cnt; 5525dd46ab5SKacheong Poon 5535dd46ab5SKacheong Poon cnt = us->us_sc_cnt; 5545dd46ab5SKacheong Poon for (i = 0; i < cnt; i++) 5555dd46ab5SKacheong Poon udp_add_mib(&us->us_sc[i]->udp_sc_mib, udp_mib); 5565dd46ab5SKacheong Poon } 5575dd46ab5SKacheong Poon 5585dd46ab5SKacheong Poon static int 5595dd46ab5SKacheong Poon udp_kstat_update(kstat_t *kp, int rw) 5605dd46ab5SKacheong Poon { 5615dd46ab5SKacheong Poon udp_named_kstat_t *udpkp; 5625dd46ab5SKacheong Poon netstackid_t stackid = (netstackid_t)(uintptr_t)kp->ks_private; 5635dd46ab5SKacheong Poon netstack_t *ns; 5645dd46ab5SKacheong Poon udp_stack_t *us; 5655dd46ab5SKacheong Poon mib2_udp_t udp_mib; 5665dd46ab5SKacheong Poon 5675dd46ab5SKacheong Poon if (rw == KSTAT_WRITE) 5685dd46ab5SKacheong Poon return (EACCES); 5695dd46ab5SKacheong Poon 5705dd46ab5SKacheong Poon ns = netstack_find_by_stackid(stackid); 5715dd46ab5SKacheong Poon if (ns == NULL) 5725dd46ab5SKacheong Poon return (-1); 5735dd46ab5SKacheong Poon us = ns->netstack_udp; 5745dd46ab5SKacheong Poon if (us == NULL) { 5755dd46ab5SKacheong Poon netstack_rele(ns); 5765dd46ab5SKacheong Poon return (-1); 5775dd46ab5SKacheong Poon } 5785dd46ab5SKacheong Poon udpkp = (udp_named_kstat_t *)kp->ks_data; 5795dd46ab5SKacheong Poon 5805dd46ab5SKacheong Poon bzero(&udp_mib, sizeof (udp_mib)); 5815dd46ab5SKacheong Poon udp_sum_mib(us, &udp_mib); 5825dd46ab5SKacheong Poon 5835dd46ab5SKacheong Poon udpkp->inDatagrams.value.ui64 = udp_mib.udpHCInDatagrams; 5845dd46ab5SKacheong Poon udpkp->inErrors.value.ui32 = udp_mib.udpInErrors; 5855dd46ab5SKacheong Poon udpkp->outDatagrams.value.ui64 = udp_mib.udpHCOutDatagrams; 5865dd46ab5SKacheong Poon udpkp->outErrors.value.ui32 = udp_mib.udpOutErrors; 5875dd46ab5SKacheong Poon netstack_rele(ns); 5885dd46ab5SKacheong Poon return (0); 5895dd46ab5SKacheong Poon } 590