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