Path: blob/main/contrib/bsnmp/snmp_mibII/mibII_udp.c
39478 views
/*1* Copyright (c) 2001-20032* Fraunhofer Institute for Open Communication Systems (FhG Fokus).3* All rights reserved.4*5* Author: Harti Brandt <[email protected]>6*7* Redistribution and use in source and binary forms, with or without8* modification, are permitted provided that the following conditions9* are met:10* 1. Redistributions of source code must retain the above copyright11* notice, this list of conditions and the following disclaimer.12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15*16* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND17* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE18* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE19* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE20* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL21* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS22* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)23* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT24* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY25* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF26* SUCH DAMAGE.27*28* $Begemot: bsnmp/snmp_mibII/mibII_udp.c,v 1.7 2005/05/23 09:03:42 brandt_h Exp $29*30* udp31*/32#include "mibII.h"33#include "mibII_oid.h"34#include <sys/socketvar.h>35#include <netinet/in_pcb.h>36#include <netinet/udp.h>37#include <netinet/ip_var.h>38#include <netinet/udp_var.h>3940struct udp_index {41struct asn_oid index;42struct xinpcb *inp;43};4445static uint64_t udp_tick;46static struct udpstat udpstat;47static struct xinpgen *xinpgen;48static size_t xinpgen_len;49static u_int udp_total;5051static u_int oidnum;52static struct udp_index *udpoids;5354static int55udp_compare(const void *p1, const void *p2)56{57const struct udp_index *t1 = p1;58const struct udp_index *t2 = p2;5960return (asn_compare_oid(&t1->index, &t2->index));61}6263static int64fetch_udp(void)65{66size_t len;67struct xinpgen *ptr;68struct xinpcb *inp;69struct udp_index *oid;70in_addr_t inaddr;7172len = sizeof(udpstat);73if (sysctlbyname("net.inet.udp.stats", &udpstat, &len, NULL, 0) == -1) {74syslog(LOG_ERR, "net.inet.udp.stats: %m");75return (-1);76}77if (len != sizeof(udpstat)) {78syslog(LOG_ERR, "net.inet.udp.stats: wrong size");79return (-1);80}8182udp_tick = get_ticks();8384len = 0;85if (sysctlbyname("net.inet.udp.pcblist", NULL, &len, NULL, 0) == -1) {86syslog(LOG_ERR, "net.inet.udp.pcblist: %m");87return (-1);88}89if (len > xinpgen_len) {90if ((ptr = realloc(xinpgen, len)) == NULL) {91syslog(LOG_ERR, "%zu: %m", len);92return (-1);93}94xinpgen = ptr;95xinpgen_len = len;96}97if (sysctlbyname("net.inet.udp.pcblist", xinpgen, &len, NULL, 0) == -1) {98syslog(LOG_ERR, "net.inet.udp.pcblist: %m");99return (-1);100}101102udp_total = 0;103for (ptr = (struct xinpgen *)(void *)((char *)xinpgen + xinpgen->xig_len);104ptr->xig_len > sizeof(struct xinpgen);105ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) {106inp = (struct xinpcb *)ptr;107if (inp->inp_gencnt > xinpgen->xig_gen ||108(inp->inp_vflag & INP_IPV4) == 0)109continue;110111udp_total++;112}113114if (oidnum < udp_total) {115oid = realloc(udpoids, udp_total * sizeof(udpoids[0]));116if (oid == NULL) {117free(udpoids);118oidnum = 0;119return (0);120}121udpoids = oid;122oidnum = udp_total;123}124125oid = udpoids;126for (ptr = (struct xinpgen *)(void *)((char *)xinpgen + xinpgen->xig_len);127ptr->xig_len > sizeof(struct xinpgen);128ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) {129inp = (struct xinpcb *)ptr;130if (inp->inp_gencnt > xinpgen->xig_gen ||131(inp->inp_vflag & INP_IPV4) == 0)132continue;133oid->inp = inp;134oid->index.len = 5;135inaddr = ntohl(inp->inp_laddr.s_addr);136oid->index.subs[0] = (inaddr >> 24) & 0xff;137oid->index.subs[1] = (inaddr >> 16) & 0xff;138oid->index.subs[2] = (inaddr >> 8) & 0xff;139oid->index.subs[3] = (inaddr >> 0) & 0xff;140oid->index.subs[4] = ntohs(inp->inp_lport);141oid++;142}143144qsort(udpoids, udp_total, sizeof(udpoids[0]), udp_compare);145146return (0);147}148149int150op_udp(struct snmp_context *ctx __unused, struct snmp_value *value,151u_int sub, u_int iidx __unused, enum snmp_op op)152{153switch (op) {154155case SNMP_OP_GETNEXT:156abort();157158case SNMP_OP_GET:159break;160161case SNMP_OP_SET:162return (SNMP_ERR_NOT_WRITEABLE);163164case SNMP_OP_ROLLBACK:165case SNMP_OP_COMMIT:166abort();167}168169if (udp_tick < this_tick)170if (fetch_udp() == -1)171return (SNMP_ERR_GENERR);172173switch (value->var.subs[sub - 1]) {174175case LEAF_udpInDatagrams:176value->v.uint32 = udpstat.udps_ipackets;177break;178179case LEAF_udpNoPorts:180value->v.uint32 = udpstat.udps_noport +181udpstat.udps_noportbcast +182udpstat.udps_noportmcast;183break;184185case LEAF_udpInErrors:186value->v.uint32 = udpstat.udps_hdrops +187udpstat.udps_badsum +188udpstat.udps_badlen +189udpstat.udps_fullsock;190break;191192case LEAF_udpOutDatagrams:193value->v.uint32 = udpstat.udps_opackets;194break;195}196return (SNMP_ERR_NOERROR);197}198199int200op_udptable(struct snmp_context *ctx __unused, struct snmp_value *value,201u_int sub, u_int iidx __unused, enum snmp_op op)202{203u_int i;204205if (udp_tick < this_tick)206if (fetch_udp() == -1)207return (SNMP_ERR_GENERR);208209switch (op) {210211case SNMP_OP_GETNEXT:212for (i = 0; i < udp_total; i++)213if (index_compare(&value->var, sub, &udpoids[i].index) < 0)214break;215if (i == udp_total)216return (SNMP_ERR_NOSUCHNAME);217index_append(&value->var, sub, &udpoids[i].index);218break;219220case SNMP_OP_GET:221for (i = 0; i < udp_total; i++)222if (index_compare(&value->var, sub, &udpoids[i].index) == 0)223break;224if (i == udp_total)225return (SNMP_ERR_NOSUCHNAME);226break;227228case SNMP_OP_SET:229return (SNMP_ERR_NOT_WRITEABLE);230231case SNMP_OP_ROLLBACK:232case SNMP_OP_COMMIT:233default:234abort();235}236237switch (value->var.subs[sub - 1]) {238239case LEAF_udpLocalAddress:240value->v.ipaddress[0] = udpoids[i].index.subs[0];241value->v.ipaddress[1] = udpoids[i].index.subs[1];242value->v.ipaddress[2] = udpoids[i].index.subs[2];243value->v.ipaddress[3] = udpoids[i].index.subs[3];244break;245246case LEAF_udpLocalPort:247value->v.integer = udpoids[i].index.subs[4];248break;249250}251return (SNMP_ERR_NOERROR);252}253254255