xref: /freebsd/contrib/bsnmp/snmp_mibII/mibII_route.c (revision 896052c10f33c29a53b63fc67d4c8238b87f5b3e)
1f06ca4afSHartmut Brandt /*
2f06ca4afSHartmut Brandt  * Copyright (c) 2001-2003
3f06ca4afSHartmut Brandt  *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4f06ca4afSHartmut Brandt  *	All rights reserved.
5f06ca4afSHartmut Brandt  *
6f06ca4afSHartmut Brandt  * Author: Harti Brandt <harti@freebsd.org>
7f06ca4afSHartmut Brandt  *
8896052c1SHartmut Brandt  * Redistribution and use in source and binary forms, with or without
9896052c1SHartmut Brandt  * modification, are permitted provided that the following conditions
10896052c1SHartmut Brandt  * are met:
11896052c1SHartmut Brandt  * 1. Redistributions of source code must retain the above copyright
12896052c1SHartmut Brandt  *    notice, this list of conditions and the following disclaimer.
13f06ca4afSHartmut Brandt  * 2. Redistributions in binary form must reproduce the above copyright
14f06ca4afSHartmut Brandt  *    notice, this list of conditions and the following disclaimer in the
15f06ca4afSHartmut Brandt  *    documentation and/or other materials provided with the distribution.
16f06ca4afSHartmut Brandt  *
17896052c1SHartmut Brandt  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18896052c1SHartmut Brandt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19896052c1SHartmut Brandt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20896052c1SHartmut Brandt  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21896052c1SHartmut Brandt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22896052c1SHartmut Brandt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23896052c1SHartmut Brandt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24896052c1SHartmut Brandt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25896052c1SHartmut Brandt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26896052c1SHartmut Brandt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27896052c1SHartmut Brandt  * SUCH DAMAGE.
28f06ca4afSHartmut Brandt  *
29896052c1SHartmut Brandt  * $Begemot: bsnmp/snmp_mibII/mibII_route.c,v 1.5 2004/08/06 08:47:04 brandt Exp $
30f06ca4afSHartmut Brandt  *
31f06ca4afSHartmut Brandt  * Routing table
32f06ca4afSHartmut Brandt  */
33f06ca4afSHartmut Brandt #include "mibII.h"
34f06ca4afSHartmut Brandt #include "mibII_oid.h"
35f06ca4afSHartmut Brandt 
36f06ca4afSHartmut Brandt struct sroute {
37f06ca4afSHartmut Brandt 	TAILQ_ENTRY(sroute) link;
38f06ca4afSHartmut Brandt 	struct asn_oid	index;
39f06ca4afSHartmut Brandt 	u_int		ifindex;
40f06ca4afSHartmut Brandt 	u_int		type;
41f06ca4afSHartmut Brandt 	u_int		proto;
42f06ca4afSHartmut Brandt };
43f06ca4afSHartmut Brandt static TAILQ_HEAD(, sroute) sroute_list = TAILQ_HEAD_INITIALIZER(sroute_list);
44f06ca4afSHartmut Brandt 
45896052c1SHartmut Brandt static uint32_t route_tick;
46f06ca4afSHartmut Brandt static u_int route_total;
47f06ca4afSHartmut Brandt 
48f06ca4afSHartmut Brandt static int
49f06ca4afSHartmut Brandt fetch_route(void)
50f06ca4afSHartmut Brandt {
51f06ca4afSHartmut Brandt 	u_char *rtab, *next;
52f06ca4afSHartmut Brandt 	size_t len;
53f06ca4afSHartmut Brandt 	struct sroute *r;
54f06ca4afSHartmut Brandt 	struct rt_msghdr *rtm;
55f06ca4afSHartmut Brandt 	struct sockaddr *addrs[RTAX_MAX];
56f06ca4afSHartmut Brandt 	struct sockaddr_in *sa, *gw;
57f06ca4afSHartmut Brandt 	struct in_addr mask, nhop;
58f06ca4afSHartmut Brandt 	in_addr_t ha;
59f06ca4afSHartmut Brandt 	struct mibif *ifp;
60f06ca4afSHartmut Brandt 
61f06ca4afSHartmut Brandt 	while ((r = TAILQ_FIRST(&sroute_list)) != NULL) {
62f06ca4afSHartmut Brandt 		TAILQ_REMOVE(&sroute_list, r, link);
63f06ca4afSHartmut Brandt 		free(r);
64f06ca4afSHartmut Brandt 	}
65f06ca4afSHartmut Brandt 	route_total = 0;
66f06ca4afSHartmut Brandt 
67f06ca4afSHartmut Brandt 	if ((rtab = mib_fetch_rtab(AF_INET, NET_RT_DUMP, 0, &len)) == NULL)
68f06ca4afSHartmut Brandt 		return (-1);
69f06ca4afSHartmut Brandt 
70f06ca4afSHartmut Brandt 	next = rtab;
71f06ca4afSHartmut Brandt 	for (next = rtab; next < rtab + len; next += rtm->rtm_msglen) {
72f06ca4afSHartmut Brandt 		rtm = (struct rt_msghdr *)(void *)next;
73f06ca4afSHartmut Brandt 		if (rtm->rtm_type != RTM_GET ||
74f06ca4afSHartmut Brandt 		    !(rtm->rtm_flags & RTF_UP))
75f06ca4afSHartmut Brandt 			continue;
76f06ca4afSHartmut Brandt 		mib_extract_addrs(rtm->rtm_addrs, (u_char *)(rtm + 1), addrs);
77f06ca4afSHartmut Brandt 
78f06ca4afSHartmut Brandt 		if (addrs[RTAX_DST] == NULL || addrs[RTAX_GATEWAY] == NULL ||
79f06ca4afSHartmut Brandt 		    addrs[RTAX_DST]->sa_family != AF_INET)
80f06ca4afSHartmut Brandt 			continue;
81f06ca4afSHartmut Brandt 
82f06ca4afSHartmut Brandt 		sa = (struct sockaddr_in *)(void *)addrs[RTAX_DST];
83f06ca4afSHartmut Brandt 
84f06ca4afSHartmut Brandt 		if (rtm->rtm_flags & RTF_HOST) {
85f06ca4afSHartmut Brandt 			mask.s_addr = 0xffffffff;
86f06ca4afSHartmut Brandt 		} else {
87f06ca4afSHartmut Brandt 			if (addrs[RTAX_NETMASK] == NULL ||
88f06ca4afSHartmut Brandt 			    addrs[RTAX_NETMASK]->sa_len == 0)
89f06ca4afSHartmut Brandt 				mask.s_addr = 0;
90f06ca4afSHartmut Brandt 			else
91f06ca4afSHartmut Brandt 				mask = ((struct sockaddr_in *)(void *)
92f06ca4afSHartmut Brandt 				    addrs[RTAX_NETMASK])->sin_addr;
93f06ca4afSHartmut Brandt 		}
94f06ca4afSHartmut Brandt 		if (addrs[RTAX_GATEWAY] == NULL) {
95f06ca4afSHartmut Brandt 			nhop.s_addr = 0;
96f06ca4afSHartmut Brandt 		} else if (rtm->rtm_flags & RTF_LLINFO) {
97f06ca4afSHartmut Brandt 			nhop = sa->sin_addr;
98f06ca4afSHartmut Brandt 		} else {
99f06ca4afSHartmut Brandt 			gw = (struct sockaddr_in *)(void *)addrs[RTAX_GATEWAY];
100f06ca4afSHartmut Brandt 			if (gw->sin_family != AF_INET)
101f06ca4afSHartmut Brandt 				continue;
102f06ca4afSHartmut Brandt 			nhop = gw->sin_addr;
103f06ca4afSHartmut Brandt 		}
104f06ca4afSHartmut Brandt 		if ((ifp = mib_find_if_sys(rtm->rtm_index)) == NULL) {
105f06ca4afSHartmut Brandt 			mib_iflist_bad = 1;
106f06ca4afSHartmut Brandt 			continue;
107f06ca4afSHartmut Brandt 		}
108f06ca4afSHartmut Brandt 
109f06ca4afSHartmut Brandt 		if ((r = malloc(sizeof(*r))) == NULL) {
110f06ca4afSHartmut Brandt 			syslog(LOG_ERR, "%m");
111f06ca4afSHartmut Brandt 			continue;
112f06ca4afSHartmut Brandt 		}
113f06ca4afSHartmut Brandt 
114f06ca4afSHartmut Brandt 		route_total++;
115f06ca4afSHartmut Brandt 
116f06ca4afSHartmut Brandt 		r->index.len = 13;
117f06ca4afSHartmut Brandt 		ha = ntohl(sa->sin_addr.s_addr);
118f06ca4afSHartmut Brandt 		r->index.subs[0] = (ha >> 24) & 0xff;
119f06ca4afSHartmut Brandt 		r->index.subs[1] = (ha >> 16) & 0xff;
120f06ca4afSHartmut Brandt 		r->index.subs[2] = (ha >>  8) & 0xff;
121f06ca4afSHartmut Brandt 		r->index.subs[3] = (ha >>  0) & 0xff;
122f06ca4afSHartmut Brandt 		ha = ntohl(mask.s_addr);
123f06ca4afSHartmut Brandt 		r->index.subs[4] = (ha >> 24) & 0xff;
124f06ca4afSHartmut Brandt 		r->index.subs[5] = (ha >> 16) & 0xff;
125f06ca4afSHartmut Brandt 		r->index.subs[6] = (ha >>  8) & 0xff;
126f06ca4afSHartmut Brandt 		r->index.subs[7] = (ha >>  0) & 0xff;
127f06ca4afSHartmut Brandt 
128f06ca4afSHartmut Brandt 		r->index.subs[8] = 0;
129f06ca4afSHartmut Brandt 
130f06ca4afSHartmut Brandt 		ha = ntohl(nhop.s_addr);
131f06ca4afSHartmut Brandt 		r->index.subs[9] = (ha >> 24) & 0xff;
132f06ca4afSHartmut Brandt 		r->index.subs[10] = (ha >> 16) & 0xff;
133f06ca4afSHartmut Brandt 		r->index.subs[11] = (ha >>  8) & 0xff;
134f06ca4afSHartmut Brandt 		r->index.subs[12] = (ha >>  0) & 0xff;
135f06ca4afSHartmut Brandt 
136f06ca4afSHartmut Brandt 		r->ifindex = ifp->index;
137f06ca4afSHartmut Brandt 
138f06ca4afSHartmut Brandt 		r->type = (rtm->rtm_flags & RTF_LLINFO) ? 3 :
139f06ca4afSHartmut Brandt 		    (rtm->rtm_flags & RTF_REJECT) ? 2 : 4;
140f06ca4afSHartmut Brandt 
141f06ca4afSHartmut Brandt 		/* cannot really know, what protocol it runs */
142f06ca4afSHartmut Brandt 		r->proto = (rtm->rtm_flags & RTF_LOCAL) ? 2 :
143f06ca4afSHartmut Brandt 		    (rtm->rtm_flags & RTF_STATIC) ? 3 :
144f06ca4afSHartmut Brandt 		    (rtm->rtm_flags & RTF_DYNAMIC) ? 4 : 10;
145f06ca4afSHartmut Brandt 
146f06ca4afSHartmut Brandt 		INSERT_OBJECT_OID(r, &sroute_list);
147f06ca4afSHartmut Brandt 	}
148f06ca4afSHartmut Brandt 
149f06ca4afSHartmut Brandt 	free(rtab);
150f06ca4afSHartmut Brandt 	route_tick = get_ticks();
151f06ca4afSHartmut Brandt 
152f06ca4afSHartmut Brandt 	return (0);
153f06ca4afSHartmut Brandt }
154f06ca4afSHartmut Brandt 
155f06ca4afSHartmut Brandt /*
156f06ca4afSHartmut Brandt  * Table
157f06ca4afSHartmut Brandt  */
158f06ca4afSHartmut Brandt int
159f06ca4afSHartmut Brandt op_route_table(struct snmp_context *ctx __unused, struct snmp_value *value,
160f06ca4afSHartmut Brandt     u_int sub, u_int iidx __unused, enum snmp_op op)
161f06ca4afSHartmut Brandt {
162f06ca4afSHartmut Brandt 	static struct sroute *r;
163f06ca4afSHartmut Brandt 
164f06ca4afSHartmut Brandt 	if (route_tick < this_tick)
165f06ca4afSHartmut Brandt 		if (fetch_route() == -1)
166f06ca4afSHartmut Brandt 			return (SNMP_ERR_GENERR);
167f06ca4afSHartmut Brandt 
168f06ca4afSHartmut Brandt 	switch (op) {
169f06ca4afSHartmut Brandt 
170f06ca4afSHartmut Brandt 	  case SNMP_OP_GETNEXT:
171f06ca4afSHartmut Brandt 		if ((r = NEXT_OBJECT_OID(&sroute_list, &value->var, sub)) == NULL)
172f06ca4afSHartmut Brandt 			return (SNMP_ERR_NOSUCHNAME);
173f06ca4afSHartmut Brandt 		index_append(&value->var, sub, &r->index);
174f06ca4afSHartmut Brandt 		break;
175f06ca4afSHartmut Brandt 
176f06ca4afSHartmut Brandt 	  case SNMP_OP_GET:
177f06ca4afSHartmut Brandt 		if ((r = FIND_OBJECT_OID(&sroute_list, &value->var, sub)) == NULL)
178f06ca4afSHartmut Brandt 			return (SNMP_ERR_NOSUCHNAME);
179f06ca4afSHartmut Brandt 		break;
180f06ca4afSHartmut Brandt 
181f06ca4afSHartmut Brandt 	  case SNMP_OP_SET:
182f06ca4afSHartmut Brandt 		if ((r = FIND_OBJECT_OID(&sroute_list, &value->var, sub)) == NULL)
183f06ca4afSHartmut Brandt 			return (SNMP_ERR_NO_CREATION);
184f06ca4afSHartmut Brandt 		return (SNMP_ERR_NOT_WRITEABLE);
185f06ca4afSHartmut Brandt 
186f06ca4afSHartmut Brandt 	  case SNMP_OP_ROLLBACK:
187f06ca4afSHartmut Brandt 	  case SNMP_OP_COMMIT:
188f06ca4afSHartmut Brandt 		abort();
189f06ca4afSHartmut Brandt 
190f06ca4afSHartmut Brandt 	  default:
191f06ca4afSHartmut Brandt 		abort();
192f06ca4afSHartmut Brandt 	}
193f06ca4afSHartmut Brandt 
194f06ca4afSHartmut Brandt 	switch (value->var.subs[sub - 1]) {
195f06ca4afSHartmut Brandt 
196f06ca4afSHartmut Brandt 	  case LEAF_ipCidrRouteDest:
197f06ca4afSHartmut Brandt 		value->v.ipaddress[0] = r->index.subs[0];
198f06ca4afSHartmut Brandt 		value->v.ipaddress[1] = r->index.subs[1];
199f06ca4afSHartmut Brandt 		value->v.ipaddress[2] = r->index.subs[2];
200f06ca4afSHartmut Brandt 		value->v.ipaddress[3] = r->index.subs[3];
201f06ca4afSHartmut Brandt 		break;
202f06ca4afSHartmut Brandt 
203f06ca4afSHartmut Brandt 	  case LEAF_ipCidrRouteMask:
204f06ca4afSHartmut Brandt 		value->v.ipaddress[0] = r->index.subs[4];
205f06ca4afSHartmut Brandt 		value->v.ipaddress[1] = r->index.subs[5];
206f06ca4afSHartmut Brandt 		value->v.ipaddress[2] = r->index.subs[6];
207f06ca4afSHartmut Brandt 		value->v.ipaddress[3] = r->index.subs[7];
208f06ca4afSHartmut Brandt 		break;
209f06ca4afSHartmut Brandt 
210f06ca4afSHartmut Brandt 	  case LEAF_ipCidrRouteTos:
211f06ca4afSHartmut Brandt 		value->v.integer = r->index.subs[8];
212f06ca4afSHartmut Brandt 		break;
213f06ca4afSHartmut Brandt 
214f06ca4afSHartmut Brandt 	  case LEAF_ipCidrRouteNextHop:
215f06ca4afSHartmut Brandt 		value->v.ipaddress[0] = r->index.subs[9];
216f06ca4afSHartmut Brandt 		value->v.ipaddress[1] = r->index.subs[10];
217f06ca4afSHartmut Brandt 		value->v.ipaddress[2] = r->index.subs[11];
218f06ca4afSHartmut Brandt 		value->v.ipaddress[3] = r->index.subs[12];
219f06ca4afSHartmut Brandt 		break;
220f06ca4afSHartmut Brandt 
221f06ca4afSHartmut Brandt 	  case LEAF_ipCidrRouteIfIndex:
222f06ca4afSHartmut Brandt 		value->v.integer = r->ifindex;
223f06ca4afSHartmut Brandt 		break;
224f06ca4afSHartmut Brandt 
225f06ca4afSHartmut Brandt 	  case LEAF_ipCidrRouteType:
226f06ca4afSHartmut Brandt 		value->v.integer = r->type;
227f06ca4afSHartmut Brandt 		break;
228f06ca4afSHartmut Brandt 
229f06ca4afSHartmut Brandt 	  case LEAF_ipCidrRouteProto:
230f06ca4afSHartmut Brandt 		value->v.integer = r->proto;
231f06ca4afSHartmut Brandt 		break;
232f06ca4afSHartmut Brandt 
233f06ca4afSHartmut Brandt 	  case LEAF_ipCidrRouteAge:
234f06ca4afSHartmut Brandt 		value->v.integer = 0;
235f06ca4afSHartmut Brandt 		break;
236f06ca4afSHartmut Brandt 
237f06ca4afSHartmut Brandt 	  case LEAF_ipCidrRouteInfo:
238f06ca4afSHartmut Brandt 		value->v.oid = oid_zeroDotZero;
239f06ca4afSHartmut Brandt 		break;
240f06ca4afSHartmut Brandt 
241f06ca4afSHartmut Brandt 	  case LEAF_ipCidrRouteNextHopAS:
242f06ca4afSHartmut Brandt 		value->v.integer = 0;
243f06ca4afSHartmut Brandt 		break;
244f06ca4afSHartmut Brandt 
245f06ca4afSHartmut Brandt 	  case LEAF_ipCidrRouteMetric1:
246f06ca4afSHartmut Brandt 	  case LEAF_ipCidrRouteMetric2:
247f06ca4afSHartmut Brandt 	  case LEAF_ipCidrRouteMetric3:
248f06ca4afSHartmut Brandt 	  case LEAF_ipCidrRouteMetric4:
249f06ca4afSHartmut Brandt 	  case LEAF_ipCidrRouteMetric5:
250f06ca4afSHartmut Brandt 		value->v.integer = -1;
251f06ca4afSHartmut Brandt 		break;
252f06ca4afSHartmut Brandt 
253f06ca4afSHartmut Brandt 	  case LEAF_ipCidrRouteStatus:
254f06ca4afSHartmut Brandt 		value->v.integer = 1;
255f06ca4afSHartmut Brandt 		break;
256f06ca4afSHartmut Brandt 	}
257f06ca4afSHartmut Brandt 	return (SNMP_ERR_NOERROR);
258f06ca4afSHartmut Brandt }
259f06ca4afSHartmut Brandt 
260f06ca4afSHartmut Brandt /*
261f06ca4afSHartmut Brandt  * scalars
262f06ca4afSHartmut Brandt  */
263f06ca4afSHartmut Brandt int
264f06ca4afSHartmut Brandt op_route(struct snmp_context *ctx __unused, struct snmp_value *value,
265f06ca4afSHartmut Brandt     u_int sub, u_int iidx __unused, enum snmp_op op)
266f06ca4afSHartmut Brandt {
267f06ca4afSHartmut Brandt 	switch (op) {
268f06ca4afSHartmut Brandt 
269f06ca4afSHartmut Brandt 	  case SNMP_OP_GETNEXT:
270f06ca4afSHartmut Brandt 		abort();
271f06ca4afSHartmut Brandt 
272f06ca4afSHartmut Brandt 	  case SNMP_OP_GET:
273f06ca4afSHartmut Brandt 		break;
274f06ca4afSHartmut Brandt 
275f06ca4afSHartmut Brandt 	  case SNMP_OP_SET:
276f06ca4afSHartmut Brandt 		return (SNMP_ERR_NOT_WRITEABLE);
277f06ca4afSHartmut Brandt 
278f06ca4afSHartmut Brandt 	  case SNMP_OP_ROLLBACK:
279f06ca4afSHartmut Brandt 	  case SNMP_OP_COMMIT:
280f06ca4afSHartmut Brandt 		abort();
281f06ca4afSHartmut Brandt 	}
282f06ca4afSHartmut Brandt 
283f06ca4afSHartmut Brandt 	if (route_tick < this_tick)
284f06ca4afSHartmut Brandt 		if (fetch_route() == -1)
285f06ca4afSHartmut Brandt 			return (SNMP_ERR_GENERR);
286f06ca4afSHartmut Brandt 
287f06ca4afSHartmut Brandt 	switch (value->var.subs[sub - 1]) {
288f06ca4afSHartmut Brandt 
289f06ca4afSHartmut Brandt 	  case LEAF_ipCidrRouteNumber:
290f06ca4afSHartmut Brandt 		value->v.uint32 = route_total;
291f06ca4afSHartmut Brandt 		break;
292f06ca4afSHartmut Brandt 
293f06ca4afSHartmut Brandt 	}
294f06ca4afSHartmut Brandt 	return (SNMP_ERR_NOERROR);
295f06ca4afSHartmut Brandt }
296