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