1122394Sharti/* 2122394Sharti * Copyright (c) 2001-2003 3122394Sharti * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4122394Sharti * All rights reserved. 5122394Sharti * 6122394Sharti * Author: Harti Brandt <harti@freebsd.org> 7310901Sngie * 8133211Sharti * Redistribution and use in source and binary forms, with or without 9133211Sharti * modification, are permitted provided that the following conditions 10133211Sharti * are met: 11133211Sharti * 1. Redistributions of source code must retain the above copyright 12133211Sharti * notice, this list of conditions and the following disclaimer. 13122394Sharti * 2. Redistributions in binary form must reproduce the above copyright 14122394Sharti * notice, this list of conditions and the following disclaimer in the 15122394Sharti * documentation and/or other materials provided with the distribution. 16310901Sngie * 17133211Sharti * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18133211Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19133211Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20133211Sharti * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 21133211Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22133211Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23133211Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24133211Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25133211Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26133211Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27133211Sharti * SUCH DAMAGE. 28122394Sharti * 29146525Sharti * $Begemot: bsnmp/snmp_mibII/mibII_udp.c,v 1.7 2005/05/23 09:03:42 brandt_h Exp $ 30122394Sharti * 31122394Sharti * udp 32122394Sharti */ 33122394Sharti#include "mibII.h" 34122394Sharti#include "mibII_oid.h" 35122394Sharti#include <sys/socketvar.h> 36122394Sharti#include <netinet/in_pcb.h> 37122394Sharti#include <netinet/udp.h> 38122394Sharti#include <netinet/ip_var.h> 39122394Sharti#include <netinet/udp_var.h> 40122394Sharti 41122394Shartistruct udp_index { 42122394Sharti struct asn_oid index; 43122394Sharti struct xinpcb *inp; 44122394Sharti}; 45122394Sharti 46146525Shartistatic uint64_t udp_tick; 47122394Shartistatic struct udpstat udpstat; 48122394Shartistatic struct xinpgen *xinpgen; 49122394Shartistatic size_t xinpgen_len; 50122394Shartistatic u_int udp_total; 51122394Sharti 52122394Shartistatic u_int oidnum; 53122394Shartistatic struct udp_index *udpoids; 54122394Sharti 55122394Shartistatic int 56122394Shartiudp_compare(const void *p1, const void *p2) 57122394Sharti{ 58122394Sharti const struct udp_index *t1 = p1; 59122394Sharti const struct udp_index *t2 = p2; 60122394Sharti 61122394Sharti return (asn_compare_oid(&t1->index, &t2->index)); 62122394Sharti} 63122394Sharti 64122394Shartistatic int 65122394Shartifetch_udp(void) 66122394Sharti{ 67122394Sharti size_t len; 68122394Sharti struct xinpgen *ptr; 69122394Sharti struct xinpcb *inp; 70122394Sharti struct udp_index *oid; 71122394Sharti in_addr_t inaddr; 72122394Sharti 73122394Sharti len = sizeof(udpstat); 74122394Sharti if (sysctlbyname("net.inet.udp.stats", &udpstat, &len, NULL, 0) == -1) { 75122394Sharti syslog(LOG_ERR, "net.inet.udp.stats: %m"); 76122394Sharti return (-1); 77122394Sharti } 78122394Sharti if (len != sizeof(udpstat)) { 79122394Sharti syslog(LOG_ERR, "net.inet.udp.stats: wrong size"); 80122394Sharti return (-1); 81122394Sharti } 82122394Sharti 83122394Sharti udp_tick = get_ticks(); 84122394Sharti 85122394Sharti len = 0; 86122394Sharti if (sysctlbyname("net.inet.udp.pcblist", NULL, &len, NULL, 0) == -1) { 87122394Sharti syslog(LOG_ERR, "net.inet.udp.pcblist: %m"); 88122394Sharti return (-1); 89122394Sharti } 90122394Sharti if (len > xinpgen_len) { 91122394Sharti if ((ptr = realloc(xinpgen, len)) == NULL) { 92122394Sharti syslog(LOG_ERR, "%zu: %m", len); 93122394Sharti return (-1); 94122394Sharti } 95122394Sharti xinpgen = ptr; 96122394Sharti xinpgen_len = len; 97122394Sharti } 98122394Sharti if (sysctlbyname("net.inet.udp.pcblist", xinpgen, &len, NULL, 0) == -1) { 99122394Sharti syslog(LOG_ERR, "net.inet.udp.pcblist: %m"); 100122394Sharti return (-1); 101122394Sharti } 102122394Sharti 103122394Sharti udp_total = 0; 104122394Sharti for (ptr = (struct xinpgen *)(void *)((char *)xinpgen + xinpgen->xig_len); 105122394Sharti ptr->xig_len > sizeof(struct xinpgen); 106122394Sharti ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) { 107122394Sharti inp = (struct xinpcb *)ptr; 108122394Sharti if (inp->xi_inp.inp_gencnt > xinpgen->xig_gen || 109122394Sharti (inp->xi_inp.inp_vflag & INP_IPV4) == 0) 110122394Sharti continue; 111122394Sharti 112122394Sharti udp_total++; 113122394Sharti } 114122394Sharti 115122394Sharti if (oidnum < udp_total) { 116122394Sharti oid = realloc(udpoids, udp_total * sizeof(udpoids[0])); 117122394Sharti if (oid == NULL) { 118122394Sharti free(udpoids); 119122394Sharti oidnum = 0; 120122394Sharti return (0); 121122394Sharti } 122122394Sharti udpoids = oid; 123122394Sharti oidnum = udp_total; 124122394Sharti } 125122394Sharti 126122394Sharti oid = udpoids; 127122394Sharti for (ptr = (struct xinpgen *)(void *)((char *)xinpgen + xinpgen->xig_len); 128122394Sharti ptr->xig_len > sizeof(struct xinpgen); 129122394Sharti ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) { 130122394Sharti inp = (struct xinpcb *)ptr; 131122394Sharti if (inp->xi_inp.inp_gencnt > xinpgen->xig_gen || 132122394Sharti (inp->xi_inp.inp_vflag & INP_IPV4) == 0) 133122394Sharti continue; 134122394Sharti oid->inp = inp; 135122394Sharti oid->index.len = 5; 136122394Sharti inaddr = ntohl(inp->xi_inp.inp_laddr.s_addr); 137122394Sharti oid->index.subs[0] = (inaddr >> 24) & 0xff; 138122394Sharti oid->index.subs[1] = (inaddr >> 16) & 0xff; 139122394Sharti oid->index.subs[2] = (inaddr >> 8) & 0xff; 140122394Sharti oid->index.subs[3] = (inaddr >> 0) & 0xff; 141122394Sharti oid->index.subs[4] = ntohs(inp->xi_inp.inp_lport); 142122394Sharti oid++; 143122394Sharti } 144122394Sharti 145122394Sharti qsort(udpoids, udp_total, sizeof(udpoids[0]), udp_compare); 146122394Sharti 147122394Sharti return (0); 148122394Sharti} 149122394Sharti 150122394Shartiint 151122394Shartiop_udp(struct snmp_context *ctx __unused, struct snmp_value *value, 152122394Sharti u_int sub, u_int iidx __unused, enum snmp_op op) 153122394Sharti{ 154122394Sharti switch (op) { 155122394Sharti 156122394Sharti case SNMP_OP_GETNEXT: 157122394Sharti abort(); 158122394Sharti 159122394Sharti case SNMP_OP_GET: 160122394Sharti break; 161122394Sharti 162122394Sharti case SNMP_OP_SET: 163122394Sharti return (SNMP_ERR_NOT_WRITEABLE); 164122394Sharti 165122394Sharti case SNMP_OP_ROLLBACK: 166122394Sharti case SNMP_OP_COMMIT: 167122394Sharti abort(); 168122394Sharti } 169122394Sharti 170122394Sharti if (udp_tick < this_tick) 171122394Sharti if (fetch_udp() == -1) 172122394Sharti return (SNMP_ERR_GENERR); 173122394Sharti 174122394Sharti switch (value->var.subs[sub - 1]) { 175122394Sharti 176122394Sharti case LEAF_udpInDatagrams: 177122394Sharti value->v.uint32 = udpstat.udps_ipackets; 178122394Sharti break; 179122394Sharti 180122394Sharti case LEAF_udpNoPorts: 181122394Sharti value->v.uint32 = udpstat.udps_noport + 182122394Sharti udpstat.udps_noportbcast + 183122394Sharti udpstat.udps_noportmcast; 184122394Sharti break; 185122394Sharti 186122394Sharti case LEAF_udpInErrors: 187122394Sharti value->v.uint32 = udpstat.udps_hdrops + 188122394Sharti udpstat.udps_badsum + 189122394Sharti udpstat.udps_badlen + 190122394Sharti udpstat.udps_fullsock; 191122394Sharti break; 192122394Sharti 193122394Sharti case LEAF_udpOutDatagrams: 194122394Sharti value->v.uint32 = udpstat.udps_opackets; 195122394Sharti break; 196122394Sharti } 197122394Sharti return (SNMP_ERR_NOERROR); 198122394Sharti} 199122394Sharti 200122394Shartiint 201122394Shartiop_udptable(struct snmp_context *ctx __unused, struct snmp_value *value, 202122394Sharti u_int sub, u_int iidx __unused, enum snmp_op op) 203122394Sharti{ 204122394Sharti u_int i; 205122394Sharti 206122394Sharti if (udp_tick < this_tick) 207122394Sharti if (fetch_udp() == -1) 208122394Sharti return (SNMP_ERR_GENERR); 209122394Sharti 210122394Sharti switch (op) { 211122394Sharti 212122394Sharti case SNMP_OP_GETNEXT: 213122394Sharti for (i = 0; i < udp_total; i++) 214122394Sharti if (index_compare(&value->var, sub, &udpoids[i].index) < 0) 215122394Sharti break; 216122394Sharti if (i == udp_total) 217122394Sharti return (SNMP_ERR_NOSUCHNAME); 218122394Sharti index_append(&value->var, sub, &udpoids[i].index); 219122394Sharti break; 220122394Sharti 221122394Sharti case SNMP_OP_GET: 222122394Sharti for (i = 0; i < udp_total; i++) 223122394Sharti if (index_compare(&value->var, sub, &udpoids[i].index) == 0) 224122394Sharti break; 225122394Sharti if (i == udp_total) 226122394Sharti return (SNMP_ERR_NOSUCHNAME); 227122394Sharti break; 228122394Sharti 229122394Sharti case SNMP_OP_SET: 230122394Sharti return (SNMP_ERR_NOT_WRITEABLE); 231122394Sharti 232122394Sharti case SNMP_OP_ROLLBACK: 233122394Sharti case SNMP_OP_COMMIT: 234122394Sharti default: 235122394Sharti abort(); 236122394Sharti } 237122394Sharti 238122394Sharti switch (value->var.subs[sub - 1]) { 239122394Sharti 240122394Sharti case LEAF_udpLocalAddress: 241122394Sharti value->v.ipaddress[0] = udpoids[i].index.subs[0]; 242122394Sharti value->v.ipaddress[1] = udpoids[i].index.subs[1]; 243122394Sharti value->v.ipaddress[2] = udpoids[i].index.subs[2]; 244122394Sharti value->v.ipaddress[3] = udpoids[i].index.subs[3]; 245122394Sharti break; 246122394Sharti 247122394Sharti case LEAF_udpLocalPort: 248122394Sharti value->v.integer = udpoids[i].index.subs[4]; 249122394Sharti break; 250122394Sharti 251122394Sharti } 252122394Sharti return (SNMP_ERR_NOERROR); 253122394Sharti} 254