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