Date: Sun, 28 Aug 2005 22:48:27 GMT From: Victor Cruceru <soc-victor@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 82724 for review Message-ID: <200508282248.j7SMmRdx082242@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=82724 Change 82724 by soc-victor@soc-victor_82.76.158.176 on 2005/08/28 22:47:35 Added the SNMP instrumentation fro UDP scalars and for the deprecated table udpTable (based on Harti's work). Also a lot of cleanup. Affected files ... .. //depot/projects/soc2005/bsnmp/usr.sbin/bsnmpd/modules/snmp_tcp_udp46/Makefile#4 edit .. //depot/projects/soc2005/bsnmp/usr.sbin/bsnmpd/modules/snmp_tcp_udp46/tcp46_snmp.c#4 edit .. //depot/projects/soc2005/bsnmp/usr.sbin/bsnmpd/modules/snmp_tcp_udp46/tcp_udp46.h#2 edit .. //depot/projects/soc2005/bsnmp/usr.sbin/bsnmpd/modules/snmp_tcp_udp46/tcp_udp46_common.c#2 edit .. //depot/projects/soc2005/bsnmp/usr.sbin/bsnmpd/modules/snmp_tcp_udp46/udp46_snmp.c#2 edit Differences ... ==== //depot/projects/soc2005/bsnmp/usr.sbin/bsnmpd/modules/snmp_tcp_udp46/Makefile#4 (text+ko) ==== @@ -37,7 +37,7 @@ WARNS?= 6 #Not having NDEBUG defined will enable assertions and a lot of output on stderr -CFLAGS+= -DNDEBUG +#CFLAGS+= -DNDEBUG XSYM= tcpMIB udpMIB ==== //depot/projects/soc2005/bsnmp/usr.sbin/bsnmpd/modules/snmp_tcp_udp46/tcp46_snmp.c#4 (text+ko) ==== @@ -497,15 +497,15 @@ syslog(LOG_ERR, "sysctlbyname(net.inet.tcp.pcblist) failed: %m"); return (-1); } - if (len > tcp_udp46_state_g.xinpgen_len) { - if ((ptr = realloc(tcp_udp46_state_g.xinpgen, len)) == NULL) { + if (len > tcp_udp46_state_g.tcp_xinpgen_len) { + if ((ptr = realloc(tcp_udp46_state_g.tcp_xinpgen, len)) == NULL) { syslog(LOG_ERR, "%zu: %m", len); return (-1); } - tcp_udp46_state_g.xinpgen = ptr; - tcp_udp46_state_g.xinpgen_len = len; + tcp_udp46_state_g.tcp_xinpgen = ptr; + tcp_udp46_state_g.tcp_xinpgen_len = len; } - if (sysctlbyname("net.inet.tcp.pcblist", tcp_udp46_state_g.xinpgen, &len, NULL, 0) == -1) { + if (sysctlbyname("net.inet.tcp.pcblist", tcp_udp46_state_g.tcp_xinpgen, &len, NULL, 0) == -1) { syslog(LOG_ERR, "sysctlbyname(net.inet.tcp.pcblist) failed: %m"); return (-1); } @@ -522,7 +522,7 @@ } /*First count the endpoints*/ - for (ptr = (struct xinpgen *)(void *)((char *)tcp_udp46_state_g.xinpgen + tcp_udp46_state_g.xinpgen->xig_len); + for (ptr = (struct xinpgen *)(void *)((char *)tcp_udp46_state_g.tcp_xinpgen + tcp_udp46_state_g.tcp_xinpgen->xig_len); ptr->xig_len > sizeof(struct xinpgen); ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) { tp = (struct xtcpcb *)ptr; @@ -539,7 +539,7 @@ } /* Ignore PCBs which were freed during copyout. */ - if (tp->xt_inp.inp_gencnt > tcp_udp46_state_g.xinpgen->xig_gen ) { + if (tp->xt_inp.inp_gencnt > tcp_udp46_state_g.tcp_xinpgen->xig_gen ) { TCP46_DPRINTF((stderr, "[%s] One tcp4 conn. ignored (freed during copyout)\n ", __func__ )); @@ -626,7 +626,7 @@ all_oid = tcp_udp46_state_g.all_tcpoids; listen_oid = tcp_udp46_state_g.listen_tcpoids; - for (ptr = (struct xinpgen *)(void *)((char *)tcp_udp46_state_g.xinpgen + tcp_udp46_state_g.xinpgen->xig_len); + for (ptr = (struct xinpgen *)(void *)((char *)tcp_udp46_state_g.tcp_xinpgen + tcp_udp46_state_g.tcp_xinpgen->xig_len); ptr->xig_len > sizeof(struct xinpgen); ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) { tp = (struct xtcpcb *)ptr; @@ -637,7 +637,7 @@ } /* Ignore PCBs which were freed during copyout. */ - if (tp->xt_inp.inp_gencnt > tcp_udp46_state_g.xinpgen->xig_gen ) { + if (tp->xt_inp.inp_gencnt > tcp_udp46_state_g.tcp_xinpgen->xig_gen ) { continue; } if ( (tp->xt_inp.inp_vflag & INP_IPV4) == INP_IPV4) { ==== //depot/projects/soc2005/bsnmp/usr.sbin/bsnmpd/modules/snmp_tcp_udp46/tcp_udp46.h#2 (text+ko) ==== @@ -42,7 +42,11 @@ #include <sys/file.h> /*for struct xfile*/ #include <stdio.h> /*for fprintf*/ #include <sys/types.h> /*for pid_t*/ +#include <netinet/udp.h> +#include <netinet/ip_var.h> +#include <netinet/udp_var.h> + /*a debug macro*/ #ifndef NDEBUG #define TCP46_DPRINTF(ARGS) do { \ @@ -63,13 +67,22 @@ pid_t so_pgid; }; +/* + * Structure used to hold info about one udp[4,6} + * endpoint + */ +struct udp_index { + struct asn_oid index; + struct xinpcb *inp; +}; + struct tcp_udp46_state { struct clockinfo clock_info; uint64_t tcp_tick; /*agent tick when this struct was last updated*/ struct tcpstat tcpstat; /*holder for tcp stats*/ - struct xinpgen *xinpgen; /*holder for data get via sysctl; malloc'd*/ - size_t xinpgen_len; /*the allocated len of the above vector */ + struct xinpgen *tcp_xinpgen; /*holder for data get via sysctl; malloc'd*/ + size_t tcp_xinpgen_len; /*the allocated len of the above vector */ u_int tcp_estab_count; /*value for the scalar named tcpCurrEstab*/ u_int tcp4_total; /*the number of tcp4 entries*/ u_int all_tcp_total; /*the number of tcp4 and tcp6 entries (without listeners)*/ @@ -84,6 +97,18 @@ struct tcp_index *listen_tcpoids; /*snmp vector for the unified v4 and v6 listners tcp table; malloc'd*/ size_t listen_tcpoids_len; /*the allocated len of the above vector */ + uint64_t udp_tick; + struct udpstat udpstat; + struct xinpgen *udp_xinpgen; + size_t udp_xinpgen_len; + u_int udp4_total; + + + struct udp_index *udp4oids; + size_t udp4oids_len; + + + struct xfile *xfiles; size_t xfiles_len; u_int xfiles_total; @@ -111,4 +136,10 @@ int fetch_xfiles(void); +/* + * Get all the UDP{4,6} info from the O/S + */ +int +fetch_udp(void); + #endif /*__TCP_UDP46_H_INCLUDED__*/ ==== //depot/projects/soc2005/bsnmp/usr.sbin/bsnmpd/modules/snmp_tcp_udp46/tcp_udp46_common.c#2 (text+ko) ==== @@ -91,6 +91,7 @@ */ static int tcp_udp46_fini(void) { + /*TCP zone*/ if (tcp_udp46_state_g.tcp4oids != NULL && tcp_udp46_state_g.tcp4oids_len > 0) { free(tcp_udp46_state_g.tcp4oids); tcp_udp46_state_g.tcp4oids = NULL; @@ -109,12 +110,27 @@ tcp_udp46_state_g.listen_tcpoids_len = 0; } - if (tcp_udp46_state_g.xinpgen != NULL && tcp_udp46_state_g.xinpgen_len > 0) { - free(tcp_udp46_state_g.xinpgen); - tcp_udp46_state_g.xinpgen = NULL; - tcp_udp46_state_g.xinpgen_len = 0; + if (tcp_udp46_state_g.tcp_xinpgen != NULL && tcp_udp46_state_g.tcp_xinpgen_len > 0) { + free(tcp_udp46_state_g.tcp_xinpgen); + tcp_udp46_state_g.tcp_xinpgen = NULL; + tcp_udp46_state_g.tcp_xinpgen_len = 0; + } + + /*UDP zone*/ + if (tcp_udp46_state_g.udp_xinpgen != NULL && tcp_udp46_state_g.udp_xinpgen_len > 0) { + free(tcp_udp46_state_g.udp_xinpgen); + tcp_udp46_state_g.udp_xinpgen = NULL; + tcp_udp46_state_g.udp_xinpgen_len = 0; + } + + + if (tcp_udp46_state_g.udp4oids != NULL && tcp_udp46_state_g.udp4oids_len > 0) { + free(tcp_udp46_state_g.udp4oids); + tcp_udp46_state_g.udp4oids = NULL; + tcp_udp46_state_g.udp4oids_len = 0; } + if (tcp_udp46_state_g.xfiles != NULL && tcp_udp46_state_g.xfiles_len > 0 ) { free(tcp_udp46_state_g.xfiles); tcp_udp46_state_g.xfiles = NULL; @@ -125,7 +141,11 @@ or_unregister(tcp46_registration_id); } - + if (udp46_registration_id > 0) { + or_unregister(udp46_registration_id); + } + + TCP46_DPRINTF((stderr, "[%s] done.\n", __func__)); return (0); @@ -187,7 +207,12 @@ } if (fetch_tcp() == -1) { - syslog(LOG_ERR, "Failed to fetch the TCP data in tcp46 module." ); + syslog(LOG_ERR, "Failed to fetch the TCP data in tcp_udp46 module." ); + } + + + if (fetch_udp() == -1) { + syslog(LOG_ERR, "Failed to fetch the UDP data in tcp-udp46 module." ); } TCP46_DPRINTF((stderr, "[%s] done.\n ", __func__)); ==== //depot/projects/soc2005/bsnmp/usr.sbin/bsnmpd/modules/snmp_tcp_udp46/udp46_snmp.c#2 (text+ko) ==== @@ -29,22 +29,306 @@ * UDP-MIB implementation for SNMPd: instrumentation for RFC 4113 covering * both IPv4 and IPv6 objects */ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt <harti@freebsd.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Begemot: bsnmp/snmp_mibII/mibII_udp.c,v 1.7 2005/05/23 09:03:42 brandt_h Exp $ + * + * udp + */ + #include "tcp_udp46.h" #include "tcp_udp46.h" #include "tcp_udp46_oid.h" #include "tcp_udp46_tree.h" +#include <assert.h> +#include <string.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/sysctl.h> +#include <syslog.h> + +static int +udp_compare(const void *p1, const void *p2) +{ + int result = 0; + const struct udp_index *t1 = p1; + const struct udp_index *t2 = p2; + assert(t1 != NULL); + assert(t2 != NULL); + if (t1 == NULL || t2 == NULL) { + return 0; + } + result = asn_compare_oid(&t1->index, &t2->index); + if ( result == 0 ) { + syslog(LOG_ERR, "udp malfunction: two equal oids."); + assert(0); + } + return result; +} + +int +fetch_udp(void) +{ + size_t len = 0; + struct xinpgen *ptr = NULL; + struct xinpcb *inp = NULL; + struct udp_index *oid = NULL; + in_addr_t inaddr; + + len = sizeof(tcp_udp46_state_g.udpstat); + if (sysctlbyname("net.inet.udp.stats", &tcp_udp46_state_g.udpstat, + &len, NULL, 0) == -1) { + syslog(LOG_ERR, "net.inet.udp.stats: %m"); + return (-1); + } + if (len != sizeof(tcp_udp46_state_g.udpstat)) { + syslog(LOG_ERR, "net.inet.udp.stats: wrong size"); + return (-1); + } + + tcp_udp46_state_g.udp_tick = get_ticks(); + + len = 0; + if (sysctlbyname("net.inet.udp.pcblist", NULL, &len, NULL, 0) == -1) { + syslog(LOG_ERR, "net.inet.udp.pcblist: %m"); + return (-1); + } + + TCP46_DPRINTF((stderr, "[%s] Got %d len at net.inet.udp.pcblist .\n", __func__, len)); + + if (len > tcp_udp46_state_g.udp_xinpgen_len) { + if ((ptr = realloc(tcp_udp46_state_g.udp_xinpgen, len)) == NULL) { + syslog(LOG_ERR, "%zu: %m", len); + return (-1); + } + tcp_udp46_state_g.udp_xinpgen = ptr; + tcp_udp46_state_g.udp_xinpgen_len = len; + memset(tcp_udp46_state_g.udp_xinpgen, 0, len); + } + if (sysctlbyname("net.inet.udp.pcblist", tcp_udp46_state_g.udp_xinpgen, + &len, NULL, 0) == -1) { + syslog(LOG_ERR, "net.inet.udp.pcblist: %m"); + return (-1); + } + + tcp_udp46_state_g.udp4_total = 0; + + ptr = (struct xinpgen *)tcp_udp46_state_g.udp_xinpgen; + for (ptr = (struct xinpgen *)((char *)ptr + ptr->xig_len); + ptr->xig_len > sizeof(struct xinpgen); + ptr = (struct xinpgen *)((char *)ptr + ptr->xig_len)) { + inp = (struct xinpcb *)ptr; + + /* Ignore sockets for protocols other than the desired one. */ + if (inp->xi_socket.xso_protocol != IPPROTO_UDP) { + continue; + } + + if (inp->xi_inp.inp_gencnt > tcp_udp46_state_g.udp_xinpgen->xig_gen) { + continue; + } + + if ((inp->xi_inp.inp_vflag & INP_IPV4) == INP_IPV4 && inp->xi_inp.inp_lport != 0){ + tcp_udp46_state_g.udp4_total++; + } + } + + if (tcp_udp46_state_g.udp4oids_len < tcp_udp46_state_g.udp4_total) { + oid = realloc(tcp_udp46_state_g.udp4oids, + tcp_udp46_state_g.udp4_total * sizeof(struct udp_index)); + if (oid == NULL) { + free(tcp_udp46_state_g.udp4oids); + tcp_udp46_state_g.udp4oids_len = 0; + return (0); + } + tcp_udp46_state_g.udp4oids = oid; + tcp_udp46_state_g.udp4oids_len = tcp_udp46_state_g.udp4_total; + } + + TCP46_DPRINTF((stderr, "[%s] Got %d udp4 endpoints, %d udp{4,6} endpoints.\n ", + __func__, + tcp_udp46_state_g.udp4_total, + 0)); + + /*Finally fill in the SNMP indexes*/ + memset(tcp_udp46_state_g.udp4oids, 0, + tcp_udp46_state_g.udp4_total * sizeof(struct udp_index) ); + + oid = tcp_udp46_state_g.udp4oids; + ptr = (struct xinpgen *)tcp_udp46_state_g.udp_xinpgen; + for (ptr = (struct xinpgen *)((char *)ptr + ptr->xig_len); + ptr->xig_len > sizeof(struct xinpgen); + ptr = (struct xinpgen *)((char *)ptr + ptr->xig_len)) { + inp = (struct xinpcb *)ptr; + /* Ignore sockets for protocols other than the desired one. */ + if (inp->xi_socket.xso_protocol != IPPROTO_UDP) { + continue; + } + + if (inp->xi_inp.inp_gencnt > tcp_udp46_state_g.udp_xinpgen->xig_gen) { + continue; + } + if ((inp->xi_inp.inp_vflag & INP_IPV4) == INP_IPV4 && inp->xi_inp.inp_lport != 0) { + oid->inp = inp; + oid->index.len = 5; + inaddr = ntohl(inp->xi_inp.inp_laddr.s_addr); + oid->index.subs[0] = (inaddr >> 24) & 0xff; + oid->index.subs[1] = (inaddr >> 16) & 0xff; + oid->index.subs[2] = (inaddr >> 8) & 0xff; + oid->index.subs[3] = (inaddr >> 0) & 0xff; + oid->index.subs[4] = ntohs(inp->xi_inp.inp_lport); + oid++; + } + } + + qsort(tcp_udp46_state_g.udp4oids, + tcp_udp46_state_g.udp4_total, + sizeof(struct udp_index), udp_compare); + + return (0); +} + + int -op_udp( struct snmp_context *ctx __unused, struct snmp_value *value __unused, - u_int sub __unused, u_int iidx __unused, enum snmp_op op __unused) { - return (SNMP_ERR_NOSUCHNAME); +op_udp(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + switch (op) { + + case SNMP_OP_GETNEXT: + abort(); + + case SNMP_OP_GET: + break; + + case SNMP_OP_SET: + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + assert(0); + return (SNMP_ERR_GENERR); + } + + if (tcp_udp46_state_g.udp_tick < this_tick) + if (fetch_udp() == -1) + return (SNMP_ERR_GENERR); + + switch (value->var.subs[sub - 1]) { + + case LEAF_udpInDatagrams: + value->v.uint32 = tcp_udp46_state_g.udpstat.udps_ipackets; + break; + + case LEAF_udpNoPorts: + value->v.uint32 = tcp_udp46_state_g.udpstat.udps_noport + + tcp_udp46_state_g.udpstat.udps_noportbcast + + tcp_udp46_state_g.udpstat.udps_noportmcast; + break; + + case LEAF_udpInErrors: + value->v.uint32 = tcp_udp46_state_g.udpstat.udps_hdrops + + tcp_udp46_state_g.udpstat.udps_badsum + + tcp_udp46_state_g.udpstat.udps_badlen + + tcp_udp46_state_g.udpstat.udps_fullsock; + break; + + case LEAF_udpOutDatagrams: + value->v.uint32 = tcp_udp46_state_g.udpstat.udps_opackets; + break; + case LEAF_udpHCInDatagrams: + value->v.counter64 = tcp_udp46_state_g.udpstat.udps_ipackets; /*FIX ME: need 64-bit stats*/ + break; + case LEAF_udpHCOutDatagrams: + value->v.counter64 = tcp_udp46_state_g.udpstat.udps_opackets; /*FIX ME: need 64-bit stats*/ + break; + + } + return (SNMP_ERR_NOERROR); + } int -op_udpTable(struct snmp_context *ctx __unused, struct snmp_value *value __unused, - u_int sub __unused, u_int iidx __unused, enum snmp_op op __unused) { - return (SNMP_ERR_NOSUCHNAME); +op_udpTable(struct snmp_context *ctx __unused, struct snmp_value *value, + u_int sub, u_int iidx __unused, enum snmp_op op) +{ + u_int i; + + if (tcp_udp46_state_g.udp_tick < this_tick) + if (fetch_udp() == -1) + return (SNMP_ERR_GENERR); + + switch (op) { + + case SNMP_OP_GETNEXT: + for (i = 0; i < tcp_udp46_state_g.udp4_total; i++) + if (index_compare(&value->var, sub, &tcp_udp46_state_g.udp4oids[i].index) < 0) + break; + if (i == tcp_udp46_state_g.udp4_total) + return (SNMP_ERR_NOSUCHNAME); + index_append(&value->var, sub, &tcp_udp46_state_g.udp4oids[i].index); + break; + + case SNMP_OP_GET: + for (i = 0; i < tcp_udp46_state_g.udp4_total; i++) + if (index_compare(&value->var, sub, &tcp_udp46_state_g.udp4oids[i].index) == 0) + break; + if (i == tcp_udp46_state_g.udp4_total) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + return (SNMP_ERR_NOT_WRITEABLE); + + case SNMP_OP_ROLLBACK: + case SNMP_OP_COMMIT: + default: + abort(); + } + + switch (value->var.subs[sub - 1]) { + + case LEAF_udpLocalAddress: + value->v.ipaddress[0] = tcp_udp46_state_g.udp4oids[i].index.subs[0]; + value->v.ipaddress[1] = tcp_udp46_state_g.udp4oids[i].index.subs[1]; + value->v.ipaddress[2] = tcp_udp46_state_g.udp4oids[i].index.subs[2]; + value->v.ipaddress[3] = tcp_udp46_state_g.udp4oids[i].index.subs[3]; + break; + + case LEAF_udpLocalPort: + value->v.integer = tcp_udp46_state_g.udp4oids[i].index.subs[4]; + break; + + } + return (SNMP_ERR_NOERROR); } int
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200508282248.j7SMmRdx082242>