1f06ca4afSHartmut Brandt /* 2f06ca4afSHartmut Brandt * Copyright (c) 2001-2003 3f06ca4afSHartmut Brandt * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4f06ca4afSHartmut Brandt * All rights reserved. 5f06ca4afSHartmut Brandt * 6f06ca4afSHartmut Brandt * Author: Harti Brandt <harti@freebsd.org> 7f06ca4afSHartmut Brandt * 8896052c1SHartmut Brandt * Redistribution and use in source and binary forms, with or without 9896052c1SHartmut Brandt * modification, are permitted provided that the following conditions 10896052c1SHartmut Brandt * are met: 11896052c1SHartmut Brandt * 1. Redistributions of source code must retain the above copyright 12896052c1SHartmut Brandt * notice, this list of conditions and the following disclaimer. 13f06ca4afSHartmut Brandt * 2. Redistributions in binary form must reproduce the above copyright 14f06ca4afSHartmut Brandt * notice, this list of conditions and the following disclaimer in the 15f06ca4afSHartmut Brandt * documentation and/or other materials provided with the distribution. 16f06ca4afSHartmut Brandt * 17896052c1SHartmut Brandt * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18896052c1SHartmut Brandt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19896052c1SHartmut Brandt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20896052c1SHartmut Brandt * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 21896052c1SHartmut Brandt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22896052c1SHartmut Brandt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23896052c1SHartmut Brandt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24896052c1SHartmut Brandt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25896052c1SHartmut Brandt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26896052c1SHartmut Brandt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27896052c1SHartmut Brandt * SUCH DAMAGE. 28f06ca4afSHartmut Brandt * 29896052c1SHartmut Brandt * $Begemot: bsnmp/snmp_mibII/mibII_udp.c,v 1.6 2004/08/06 08:47:05 brandt Exp $ 30f06ca4afSHartmut Brandt * 31f06ca4afSHartmut Brandt * udp 32f06ca4afSHartmut Brandt */ 33f06ca4afSHartmut Brandt #include "mibII.h" 34f06ca4afSHartmut Brandt #include "mibII_oid.h" 35f06ca4afSHartmut Brandt #include <sys/socketvar.h> 36f06ca4afSHartmut Brandt #include <netinet/in_pcb.h> 37f06ca4afSHartmut Brandt #include <netinet/udp.h> 38f06ca4afSHartmut Brandt #include <netinet/ip_var.h> 39f06ca4afSHartmut Brandt #include <netinet/udp_var.h> 40f06ca4afSHartmut Brandt 41f06ca4afSHartmut Brandt struct udp_index { 42f06ca4afSHartmut Brandt struct asn_oid index; 43f06ca4afSHartmut Brandt struct xinpcb *inp; 44f06ca4afSHartmut Brandt }; 45f06ca4afSHartmut Brandt 46896052c1SHartmut Brandt static uint32_t udp_tick; 47f06ca4afSHartmut Brandt static struct udpstat udpstat; 48f06ca4afSHartmut Brandt static struct xinpgen *xinpgen; 49f06ca4afSHartmut Brandt static size_t xinpgen_len; 50f06ca4afSHartmut Brandt static u_int udp_total; 51f06ca4afSHartmut Brandt 52f06ca4afSHartmut Brandt static u_int oidnum; 53f06ca4afSHartmut Brandt static struct udp_index *udpoids; 54f06ca4afSHartmut Brandt 55f06ca4afSHartmut Brandt static int 56f06ca4afSHartmut Brandt udp_compare(const void *p1, const void *p2) 57f06ca4afSHartmut Brandt { 58f06ca4afSHartmut Brandt const struct udp_index *t1 = p1; 59f06ca4afSHartmut Brandt const struct udp_index *t2 = p2; 60f06ca4afSHartmut Brandt 61f06ca4afSHartmut Brandt return (asn_compare_oid(&t1->index, &t2->index)); 62f06ca4afSHartmut Brandt } 63f06ca4afSHartmut Brandt 64f06ca4afSHartmut Brandt static int 65f06ca4afSHartmut Brandt fetch_udp(void) 66f06ca4afSHartmut Brandt { 67f06ca4afSHartmut Brandt size_t len; 68f06ca4afSHartmut Brandt struct xinpgen *ptr; 69f06ca4afSHartmut Brandt struct xinpcb *inp; 70f06ca4afSHartmut Brandt struct udp_index *oid; 71f06ca4afSHartmut Brandt in_addr_t inaddr; 72f06ca4afSHartmut Brandt 73f06ca4afSHartmut Brandt len = sizeof(udpstat); 74f06ca4afSHartmut Brandt if (sysctlbyname("net.inet.udp.stats", &udpstat, &len, NULL, 0) == -1) { 75f06ca4afSHartmut Brandt syslog(LOG_ERR, "net.inet.udp.stats: %m"); 76f06ca4afSHartmut Brandt return (-1); 77f06ca4afSHartmut Brandt } 78f06ca4afSHartmut Brandt if (len != sizeof(udpstat)) { 79f06ca4afSHartmut Brandt syslog(LOG_ERR, "net.inet.udp.stats: wrong size"); 80f06ca4afSHartmut Brandt return (-1); 81f06ca4afSHartmut Brandt } 82f06ca4afSHartmut Brandt 83f06ca4afSHartmut Brandt udp_tick = get_ticks(); 84f06ca4afSHartmut Brandt 85f06ca4afSHartmut Brandt len = 0; 86f06ca4afSHartmut Brandt if (sysctlbyname("net.inet.udp.pcblist", NULL, &len, NULL, 0) == -1) { 87f06ca4afSHartmut Brandt syslog(LOG_ERR, "net.inet.udp.pcblist: %m"); 88f06ca4afSHartmut Brandt return (-1); 89f06ca4afSHartmut Brandt } 90f06ca4afSHartmut Brandt if (len > xinpgen_len) { 91f06ca4afSHartmut Brandt if ((ptr = realloc(xinpgen, len)) == NULL) { 92f06ca4afSHartmut Brandt syslog(LOG_ERR, "%zu: %m", len); 93f06ca4afSHartmut Brandt return (-1); 94f06ca4afSHartmut Brandt } 95f06ca4afSHartmut Brandt xinpgen = ptr; 96f06ca4afSHartmut Brandt xinpgen_len = len; 97f06ca4afSHartmut Brandt } 98f06ca4afSHartmut Brandt if (sysctlbyname("net.inet.udp.pcblist", xinpgen, &len, NULL, 0) == -1) { 99f06ca4afSHartmut Brandt syslog(LOG_ERR, "net.inet.udp.pcblist: %m"); 100f06ca4afSHartmut Brandt return (-1); 101f06ca4afSHartmut Brandt } 102f06ca4afSHartmut Brandt 103f06ca4afSHartmut Brandt udp_total = 0; 104f06ca4afSHartmut Brandt for (ptr = (struct xinpgen *)(void *)((char *)xinpgen + xinpgen->xig_len); 105f06ca4afSHartmut Brandt ptr->xig_len > sizeof(struct xinpgen); 106f06ca4afSHartmut Brandt ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) { 107f06ca4afSHartmut Brandt inp = (struct xinpcb *)ptr; 108f06ca4afSHartmut Brandt if (inp->xi_inp.inp_gencnt > xinpgen->xig_gen || 109f06ca4afSHartmut Brandt (inp->xi_inp.inp_vflag & INP_IPV4) == 0) 110f06ca4afSHartmut Brandt continue; 111f06ca4afSHartmut Brandt 112f06ca4afSHartmut Brandt udp_total++; 113f06ca4afSHartmut Brandt } 114f06ca4afSHartmut Brandt 115f06ca4afSHartmut Brandt if (oidnum < udp_total) { 116f06ca4afSHartmut Brandt oid = realloc(udpoids, udp_total * sizeof(udpoids[0])); 117f06ca4afSHartmut Brandt if (oid == NULL) { 118f06ca4afSHartmut Brandt free(udpoids); 119f06ca4afSHartmut Brandt oidnum = 0; 120f06ca4afSHartmut Brandt return (0); 121f06ca4afSHartmut Brandt } 122f06ca4afSHartmut Brandt udpoids = oid; 123f06ca4afSHartmut Brandt oidnum = udp_total; 124f06ca4afSHartmut Brandt } 125f06ca4afSHartmut Brandt 126f06ca4afSHartmut Brandt oid = udpoids; 127f06ca4afSHartmut Brandt for (ptr = (struct xinpgen *)(void *)((char *)xinpgen + xinpgen->xig_len); 128f06ca4afSHartmut Brandt ptr->xig_len > sizeof(struct xinpgen); 129f06ca4afSHartmut Brandt ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) { 130f06ca4afSHartmut Brandt inp = (struct xinpcb *)ptr; 131f06ca4afSHartmut Brandt if (inp->xi_inp.inp_gencnt > xinpgen->xig_gen || 132f06ca4afSHartmut Brandt (inp->xi_inp.inp_vflag & INP_IPV4) == 0) 133f06ca4afSHartmut Brandt continue; 134f06ca4afSHartmut Brandt oid->inp = inp; 135f06ca4afSHartmut Brandt oid->index.len = 5; 136f06ca4afSHartmut Brandt inaddr = ntohl(inp->xi_inp.inp_laddr.s_addr); 137f06ca4afSHartmut Brandt oid->index.subs[0] = (inaddr >> 24) & 0xff; 138f06ca4afSHartmut Brandt oid->index.subs[1] = (inaddr >> 16) & 0xff; 139f06ca4afSHartmut Brandt oid->index.subs[2] = (inaddr >> 8) & 0xff; 140f06ca4afSHartmut Brandt oid->index.subs[3] = (inaddr >> 0) & 0xff; 141f06ca4afSHartmut Brandt oid->index.subs[4] = ntohs(inp->xi_inp.inp_lport); 142f06ca4afSHartmut Brandt oid++; 143f06ca4afSHartmut Brandt } 144f06ca4afSHartmut Brandt 145f06ca4afSHartmut Brandt qsort(udpoids, udp_total, sizeof(udpoids[0]), udp_compare); 146f06ca4afSHartmut Brandt 147f06ca4afSHartmut Brandt return (0); 148f06ca4afSHartmut Brandt } 149f06ca4afSHartmut Brandt 150f06ca4afSHartmut Brandt int 151f06ca4afSHartmut Brandt op_udp(struct snmp_context *ctx __unused, struct snmp_value *value, 152f06ca4afSHartmut Brandt u_int sub, u_int iidx __unused, enum snmp_op op) 153f06ca4afSHartmut Brandt { 154f06ca4afSHartmut Brandt switch (op) { 155f06ca4afSHartmut Brandt 156f06ca4afSHartmut Brandt case SNMP_OP_GETNEXT: 157f06ca4afSHartmut Brandt abort(); 158f06ca4afSHartmut Brandt 159f06ca4afSHartmut Brandt case SNMP_OP_GET: 160f06ca4afSHartmut Brandt break; 161f06ca4afSHartmut Brandt 162f06ca4afSHartmut Brandt case SNMP_OP_SET: 163f06ca4afSHartmut Brandt return (SNMP_ERR_NOT_WRITEABLE); 164f06ca4afSHartmut Brandt 165f06ca4afSHartmut Brandt case SNMP_OP_ROLLBACK: 166f06ca4afSHartmut Brandt case SNMP_OP_COMMIT: 167f06ca4afSHartmut Brandt abort(); 168f06ca4afSHartmut Brandt } 169f06ca4afSHartmut Brandt 170f06ca4afSHartmut Brandt if (udp_tick < this_tick) 171f06ca4afSHartmut Brandt if (fetch_udp() == -1) 172f06ca4afSHartmut Brandt return (SNMP_ERR_GENERR); 173f06ca4afSHartmut Brandt 174f06ca4afSHartmut Brandt switch (value->var.subs[sub - 1]) { 175f06ca4afSHartmut Brandt 176f06ca4afSHartmut Brandt case LEAF_udpInDatagrams: 177f06ca4afSHartmut Brandt value->v.uint32 = udpstat.udps_ipackets; 178f06ca4afSHartmut Brandt break; 179f06ca4afSHartmut Brandt 180f06ca4afSHartmut Brandt case LEAF_udpNoPorts: 181f06ca4afSHartmut Brandt value->v.uint32 = udpstat.udps_noport + 182f06ca4afSHartmut Brandt udpstat.udps_noportbcast + 183f06ca4afSHartmut Brandt udpstat.udps_noportmcast; 184f06ca4afSHartmut Brandt break; 185f06ca4afSHartmut Brandt 186f06ca4afSHartmut Brandt case LEAF_udpInErrors: 187f06ca4afSHartmut Brandt value->v.uint32 = udpstat.udps_hdrops + 188f06ca4afSHartmut Brandt udpstat.udps_badsum + 189f06ca4afSHartmut Brandt udpstat.udps_badlen + 190f06ca4afSHartmut Brandt udpstat.udps_fullsock; 191f06ca4afSHartmut Brandt break; 192f06ca4afSHartmut Brandt 193f06ca4afSHartmut Brandt case LEAF_udpOutDatagrams: 194f06ca4afSHartmut Brandt value->v.uint32 = udpstat.udps_opackets; 195f06ca4afSHartmut Brandt break; 196f06ca4afSHartmut Brandt } 197f06ca4afSHartmut Brandt return (SNMP_ERR_NOERROR); 198f06ca4afSHartmut Brandt } 199f06ca4afSHartmut Brandt 200f06ca4afSHartmut Brandt int 201f06ca4afSHartmut Brandt op_udptable(struct snmp_context *ctx __unused, struct snmp_value *value, 202f06ca4afSHartmut Brandt u_int sub, u_int iidx __unused, enum snmp_op op) 203f06ca4afSHartmut Brandt { 204f06ca4afSHartmut Brandt u_int i; 205f06ca4afSHartmut Brandt 206f06ca4afSHartmut Brandt if (udp_tick < this_tick) 207f06ca4afSHartmut Brandt if (fetch_udp() == -1) 208f06ca4afSHartmut Brandt return (SNMP_ERR_GENERR); 209f06ca4afSHartmut Brandt 210f06ca4afSHartmut Brandt switch (op) { 211f06ca4afSHartmut Brandt 212f06ca4afSHartmut Brandt case SNMP_OP_GETNEXT: 213f06ca4afSHartmut Brandt for (i = 0; i < udp_total; i++) 214f06ca4afSHartmut Brandt if (index_compare(&value->var, sub, &udpoids[i].index) < 0) 215f06ca4afSHartmut Brandt break; 216f06ca4afSHartmut Brandt if (i == udp_total) 217f06ca4afSHartmut Brandt return (SNMP_ERR_NOSUCHNAME); 218f06ca4afSHartmut Brandt index_append(&value->var, sub, &udpoids[i].index); 219f06ca4afSHartmut Brandt break; 220f06ca4afSHartmut Brandt 221f06ca4afSHartmut Brandt case SNMP_OP_GET: 222f06ca4afSHartmut Brandt for (i = 0; i < udp_total; i++) 223f06ca4afSHartmut Brandt if (index_compare(&value->var, sub, &udpoids[i].index) == 0) 224f06ca4afSHartmut Brandt break; 225f06ca4afSHartmut Brandt if (i == udp_total) 226f06ca4afSHartmut Brandt return (SNMP_ERR_NOSUCHNAME); 227f06ca4afSHartmut Brandt break; 228f06ca4afSHartmut Brandt 229f06ca4afSHartmut Brandt case SNMP_OP_SET: 230f06ca4afSHartmut Brandt return (SNMP_ERR_NOT_WRITEABLE); 231f06ca4afSHartmut Brandt 232f06ca4afSHartmut Brandt case SNMP_OP_ROLLBACK: 233f06ca4afSHartmut Brandt case SNMP_OP_COMMIT: 234f06ca4afSHartmut Brandt default: 235f06ca4afSHartmut Brandt abort(); 236f06ca4afSHartmut Brandt } 237f06ca4afSHartmut Brandt 238f06ca4afSHartmut Brandt switch (value->var.subs[sub - 1]) { 239f06ca4afSHartmut Brandt 240f06ca4afSHartmut Brandt case LEAF_udpLocalAddress: 241f06ca4afSHartmut Brandt value->v.ipaddress[0] = udpoids[i].index.subs[0]; 242f06ca4afSHartmut Brandt value->v.ipaddress[1] = udpoids[i].index.subs[1]; 243f06ca4afSHartmut Brandt value->v.ipaddress[2] = udpoids[i].index.subs[2]; 244f06ca4afSHartmut Brandt value->v.ipaddress[3] = udpoids[i].index.subs[3]; 245f06ca4afSHartmut Brandt break; 246f06ca4afSHartmut Brandt 247f06ca4afSHartmut Brandt case LEAF_udpLocalPort: 248f06ca4afSHartmut Brandt value->v.integer = udpoids[i].index.subs[4]; 249f06ca4afSHartmut Brandt break; 250f06ca4afSHartmut Brandt 251f06ca4afSHartmut Brandt } 252f06ca4afSHartmut Brandt return (SNMP_ERR_NOERROR); 253f06ca4afSHartmut Brandt } 254