Deleted Added
full compact
mibII_interfaces.c (146525) mibII_interfaces.c (151970)
1/*
2 * Copyright (c) 2001-2003
3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4 * All rights reserved.
5 *
6 * Author: Harti Brandt <harti@freebsd.org>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
1/*
2 * Copyright (c) 2001-2003
3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4 * All rights reserved.
5 *
6 * Author: Harti Brandt <harti@freebsd.org>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $Begemot: bsnmp/snmp_mibII/mibII_interfaces.c,v 1.15 2005/05/23 09:03:39 brandt_h Exp $
29 * $Begemot: bsnmp/snmp_mibII/mibII_interfaces.c,v 1.16 2005/11/02 12:07:40 brandt_h Exp $
30 *
31 * Interfaces group.
32 */
33#include "mibII.h"
34#include "mibII_oid.h"
35
36/*
37 * This structure catches all changes to a interface entry
38 */
39struct ifchange {
40 struct snmp_dependency dep;
41
42 u_int ifindex;
43
44 uint32_t set;
45 int promisc;
46 int admin;
47 int traps;
48
49 uint32_t rb;
50 int rb_flags;
51 int rb_traps;
52};
53#define IFC_PROMISC 0x0001
54#define IFC_ADMIN 0x0002
55#define IFC_TRAPS 0x0004
56#define IFRB_FLAGS 0x0001
57#define IFRB_TRAPS 0x0002
58
59static const struct asn_oid
60 oid_ifTable = OIDX_ifTable;
61
62/*
63 * This function handles all changes to the interface table and interface
64 * extension table.
65 */
66static int
67ifchange_func(struct snmp_context *ctx __unused, struct snmp_dependency *dep,
68 enum snmp_depop op)
69{
70 struct ifchange *ifc = (struct ifchange *)dep;
71 struct mibif *ifp;
72 struct ifreq ifr, ifr1;
73
74 if ((ifp = mib_find_if(ifc->ifindex)) == NULL)
75 return (SNMP_ERR_NO_CREATION);
76
77 switch (op) {
78
79 case SNMP_DEPOP_COMMIT:
80 strncpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
81 if (ioctl(mib_netsock, SIOCGIFFLAGS, &ifr) == -1) {
82 syslog(LOG_ERR, "GIFFLAGS(%s): %m", ifp->name);
83 return (SNMP_ERR_GENERR);
84 }
85 if (ifc->set & IFC_PROMISC) {
86 ifr.ifr_flags &= ~IFF_PROMISC;
87 if (ifc->promisc)
88 ifr.ifr_flags |= IFF_PROMISC;
89 ifc->rb |= IFRB_FLAGS;
90 }
91 if (ifc->set & IFC_ADMIN) {
92 ifr.ifr_flags &= ~IFF_UP;
93 if (ifc->admin)
94 ifr.ifr_flags |= IFF_UP;
95 ifc->rb |= IFRB_FLAGS;
96 }
97 if (ifc->rb & IFRB_FLAGS) {
98 strncpy(ifr1.ifr_name, ifp->name, sizeof(ifr1.ifr_name));
99 if (ioctl(mib_netsock, SIOCGIFFLAGS, &ifr1) == -1) {
100 syslog(LOG_ERR, "GIFFLAGS(%s): %m", ifp->name);
101 return (SNMP_ERR_GENERR);
102 }
103 ifc->rb_flags = ifr1.ifr_flags;
104 if (ioctl(mib_netsock, SIOCSIFFLAGS, &ifr) == -1) {
105 syslog(LOG_ERR, "SIFFLAGS(%s): %m", ifp->name);
106 return (SNMP_ERR_GENERR);
107 }
108 (void)mib_fetch_ifmib(ifp);
109 }
110 if (ifc->set & IFC_TRAPS) {
111 ifc->rb |= IFRB_TRAPS;
112 ifc->rb_traps = ifp->trap_enable;
113 ifp->trap_enable = ifc->traps;
114 }
115 return (SNMP_ERR_NOERROR);
116
117 case SNMP_DEPOP_ROLLBACK:
118 if (ifc->rb & IFRB_FLAGS) {
119 strncpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
120 ifr.ifr_flags = ifc->rb_flags;
121 if (ioctl(mib_netsock, SIOCSIFFLAGS, &ifr) == -1) {
122 syslog(LOG_ERR, "SIFFLAGS(%s): %m", ifp->name);
123 return (SNMP_ERR_UNDO_FAILED);
124 }
125 (void)mib_fetch_ifmib(ifp);
126 }
127 if (ifc->rb & IFRB_TRAPS)
128 ifp->trap_enable = ifc->rb_traps;
129 return (SNMP_ERR_NOERROR);
130
131 case SNMP_DEPOP_FINISH:
132 return (SNMP_ERR_NOERROR);
133
134 }
135 abort();
136}
137
138/*
139 * Return difference to daemon start time in ticks truncated to a
140 * 32-bit value. If the timeval is 0 then return 0.
141 */
142static uint32_t
143ticks_get_timeval(struct timeval *tv)
144{
145 uint64_t v;
146
147 if (tv->tv_sec != 0 || tv->tv_usec != 0) {
148 v = 100ULL * tv->tv_sec + tv->tv_usec / 10000ULL;
149 if (v > start_tick)
150 return (v - start_tick);
151 }
152 return (0);
153}
154
155/*
156 * Scalars
157 */
158int
159op_interfaces(struct snmp_context *ctx __unused, struct snmp_value *value,
160 u_int sub, u_int idx __unused, enum snmp_op op)
161{
162 switch (op) {
163
164 case SNMP_OP_GETNEXT:
165 abort();
166
167 case SNMP_OP_GET:
168 break;
169
170 case SNMP_OP_SET:
171 return (SNMP_ERR_NOT_WRITEABLE);
172
173 case SNMP_OP_ROLLBACK:
174 case SNMP_OP_COMMIT:
175 abort();
176 }
177
178 switch (value->var.subs[sub - 1]) {
179
180 case LEAF_ifNumber:
181 value->v.integer = mib_if_number;
182 break;
183 }
184 return (SNMP_ERR_NOERROR);
185}
186
187/*
188 * Iftable entry
189 */
190int
191op_ifentry(struct snmp_context *ctx, struct snmp_value *value,
192 u_int sub, u_int iidx __unused, enum snmp_op op)
193{
194 struct mibif *ifp = NULL;
195 int ret;
196 struct ifchange *ifc;
197 struct asn_oid idx;
198
199 switch (op) {
200
201 case SNMP_OP_GETNEXT:
202 if ((ifp = NEXT_OBJECT_INT(&mibif_list, &value->var, sub)) == NULL)
203 return (SNMP_ERR_NOSUCHNAME);
204 value->var.len = sub + 1;
205 value->var.subs[sub] = ifp->index;
206 break;
207
208 case SNMP_OP_GET:
209 if (value->var.len - sub != 1)
210 return (SNMP_ERR_NOSUCHNAME);
211 if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)
212 return (SNMP_ERR_NOSUCHNAME);
213 break;
214
215 case SNMP_OP_SET:
216 if (value->var.len - sub != 1)
217 return (SNMP_ERR_NO_CREATION);
218 if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)
219 return (SNMP_ERR_NO_CREATION);
220 if (value->var.subs[sub - 1] != LEAF_ifAdminStatus)
221 return (SNMP_ERR_NOT_WRITEABLE);
222
223 idx.len = 1;
224 idx.subs[0] = ifp->index;
225
226 if (value->v.integer != 1 && value->v.integer != 2)
227 return (SNMP_ERR_WRONG_VALUE);
228
229 if ((ifc = (struct ifchange *)snmp_dep_lookup(ctx,
230 &oid_ifTable, &idx, sizeof(*ifc), ifchange_func)) == NULL)
231 return (SNMP_ERR_RES_UNAVAIL);
232 ifc->ifindex = ifp->index;
233
234 if (ifc->set & IFC_ADMIN)
235 return (SNMP_ERR_INCONS_VALUE);
236 ifc->set |= IFC_ADMIN;
237 ifc->admin = (value->v.integer == 1) ? 1 : 0;
238
239 return (SNMP_ERR_NOERROR);
240
241 case SNMP_OP_ROLLBACK:
242 case SNMP_OP_COMMIT:
243 return (SNMP_ERR_NOERROR);
244 }
245
246 if (ifp->mibtick < this_tick)
247 (void)mib_fetch_ifmib(ifp);
248
249 ret = SNMP_ERR_NOERROR;
250 switch (value->var.subs[sub - 1]) {
251
252 case LEAF_ifIndex:
253 value->v.integer = ifp->index;
254 break;
255
256 case LEAF_ifDescr:
257 ret = string_get(value, ifp->descr, -1);
258 break;
259
260 case LEAF_ifType:
261 value->v.integer = ifp->mib.ifmd_data.ifi_type;
262 break;
263
264 case LEAF_ifMtu:
265 value->v.integer = ifp->mib.ifmd_data.ifi_mtu;
266 break;
267
268 case LEAF_ifSpeed:
269 value->v.integer = ifp->mib.ifmd_data.ifi_baudrate;
270 break;
271
272 case LEAF_ifPhysAddress:
273 ret = string_get(value, ifp->physaddr,
274 ifp->physaddrlen);
275 break;
276
277 case LEAF_ifAdminStatus:
278 value->v.integer =
279 (ifp->mib.ifmd_flags & IFF_UP) ? 1 : 2;
280 break;
281
282 case LEAF_ifOperStatus:
30 *
31 * Interfaces group.
32 */
33#include "mibII.h"
34#include "mibII_oid.h"
35
36/*
37 * This structure catches all changes to a interface entry
38 */
39struct ifchange {
40 struct snmp_dependency dep;
41
42 u_int ifindex;
43
44 uint32_t set;
45 int promisc;
46 int admin;
47 int traps;
48
49 uint32_t rb;
50 int rb_flags;
51 int rb_traps;
52};
53#define IFC_PROMISC 0x0001
54#define IFC_ADMIN 0x0002
55#define IFC_TRAPS 0x0004
56#define IFRB_FLAGS 0x0001
57#define IFRB_TRAPS 0x0002
58
59static const struct asn_oid
60 oid_ifTable = OIDX_ifTable;
61
62/*
63 * This function handles all changes to the interface table and interface
64 * extension table.
65 */
66static int
67ifchange_func(struct snmp_context *ctx __unused, struct snmp_dependency *dep,
68 enum snmp_depop op)
69{
70 struct ifchange *ifc = (struct ifchange *)dep;
71 struct mibif *ifp;
72 struct ifreq ifr, ifr1;
73
74 if ((ifp = mib_find_if(ifc->ifindex)) == NULL)
75 return (SNMP_ERR_NO_CREATION);
76
77 switch (op) {
78
79 case SNMP_DEPOP_COMMIT:
80 strncpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
81 if (ioctl(mib_netsock, SIOCGIFFLAGS, &ifr) == -1) {
82 syslog(LOG_ERR, "GIFFLAGS(%s): %m", ifp->name);
83 return (SNMP_ERR_GENERR);
84 }
85 if (ifc->set & IFC_PROMISC) {
86 ifr.ifr_flags &= ~IFF_PROMISC;
87 if (ifc->promisc)
88 ifr.ifr_flags |= IFF_PROMISC;
89 ifc->rb |= IFRB_FLAGS;
90 }
91 if (ifc->set & IFC_ADMIN) {
92 ifr.ifr_flags &= ~IFF_UP;
93 if (ifc->admin)
94 ifr.ifr_flags |= IFF_UP;
95 ifc->rb |= IFRB_FLAGS;
96 }
97 if (ifc->rb & IFRB_FLAGS) {
98 strncpy(ifr1.ifr_name, ifp->name, sizeof(ifr1.ifr_name));
99 if (ioctl(mib_netsock, SIOCGIFFLAGS, &ifr1) == -1) {
100 syslog(LOG_ERR, "GIFFLAGS(%s): %m", ifp->name);
101 return (SNMP_ERR_GENERR);
102 }
103 ifc->rb_flags = ifr1.ifr_flags;
104 if (ioctl(mib_netsock, SIOCSIFFLAGS, &ifr) == -1) {
105 syslog(LOG_ERR, "SIFFLAGS(%s): %m", ifp->name);
106 return (SNMP_ERR_GENERR);
107 }
108 (void)mib_fetch_ifmib(ifp);
109 }
110 if (ifc->set & IFC_TRAPS) {
111 ifc->rb |= IFRB_TRAPS;
112 ifc->rb_traps = ifp->trap_enable;
113 ifp->trap_enable = ifc->traps;
114 }
115 return (SNMP_ERR_NOERROR);
116
117 case SNMP_DEPOP_ROLLBACK:
118 if (ifc->rb & IFRB_FLAGS) {
119 strncpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
120 ifr.ifr_flags = ifc->rb_flags;
121 if (ioctl(mib_netsock, SIOCSIFFLAGS, &ifr) == -1) {
122 syslog(LOG_ERR, "SIFFLAGS(%s): %m", ifp->name);
123 return (SNMP_ERR_UNDO_FAILED);
124 }
125 (void)mib_fetch_ifmib(ifp);
126 }
127 if (ifc->rb & IFRB_TRAPS)
128 ifp->trap_enable = ifc->rb_traps;
129 return (SNMP_ERR_NOERROR);
130
131 case SNMP_DEPOP_FINISH:
132 return (SNMP_ERR_NOERROR);
133
134 }
135 abort();
136}
137
138/*
139 * Return difference to daemon start time in ticks truncated to a
140 * 32-bit value. If the timeval is 0 then return 0.
141 */
142static uint32_t
143ticks_get_timeval(struct timeval *tv)
144{
145 uint64_t v;
146
147 if (tv->tv_sec != 0 || tv->tv_usec != 0) {
148 v = 100ULL * tv->tv_sec + tv->tv_usec / 10000ULL;
149 if (v > start_tick)
150 return (v - start_tick);
151 }
152 return (0);
153}
154
155/*
156 * Scalars
157 */
158int
159op_interfaces(struct snmp_context *ctx __unused, struct snmp_value *value,
160 u_int sub, u_int idx __unused, enum snmp_op op)
161{
162 switch (op) {
163
164 case SNMP_OP_GETNEXT:
165 abort();
166
167 case SNMP_OP_GET:
168 break;
169
170 case SNMP_OP_SET:
171 return (SNMP_ERR_NOT_WRITEABLE);
172
173 case SNMP_OP_ROLLBACK:
174 case SNMP_OP_COMMIT:
175 abort();
176 }
177
178 switch (value->var.subs[sub - 1]) {
179
180 case LEAF_ifNumber:
181 value->v.integer = mib_if_number;
182 break;
183 }
184 return (SNMP_ERR_NOERROR);
185}
186
187/*
188 * Iftable entry
189 */
190int
191op_ifentry(struct snmp_context *ctx, struct snmp_value *value,
192 u_int sub, u_int iidx __unused, enum snmp_op op)
193{
194 struct mibif *ifp = NULL;
195 int ret;
196 struct ifchange *ifc;
197 struct asn_oid idx;
198
199 switch (op) {
200
201 case SNMP_OP_GETNEXT:
202 if ((ifp = NEXT_OBJECT_INT(&mibif_list, &value->var, sub)) == NULL)
203 return (SNMP_ERR_NOSUCHNAME);
204 value->var.len = sub + 1;
205 value->var.subs[sub] = ifp->index;
206 break;
207
208 case SNMP_OP_GET:
209 if (value->var.len - sub != 1)
210 return (SNMP_ERR_NOSUCHNAME);
211 if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)
212 return (SNMP_ERR_NOSUCHNAME);
213 break;
214
215 case SNMP_OP_SET:
216 if (value->var.len - sub != 1)
217 return (SNMP_ERR_NO_CREATION);
218 if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)
219 return (SNMP_ERR_NO_CREATION);
220 if (value->var.subs[sub - 1] != LEAF_ifAdminStatus)
221 return (SNMP_ERR_NOT_WRITEABLE);
222
223 idx.len = 1;
224 idx.subs[0] = ifp->index;
225
226 if (value->v.integer != 1 && value->v.integer != 2)
227 return (SNMP_ERR_WRONG_VALUE);
228
229 if ((ifc = (struct ifchange *)snmp_dep_lookup(ctx,
230 &oid_ifTable, &idx, sizeof(*ifc), ifchange_func)) == NULL)
231 return (SNMP_ERR_RES_UNAVAIL);
232 ifc->ifindex = ifp->index;
233
234 if (ifc->set & IFC_ADMIN)
235 return (SNMP_ERR_INCONS_VALUE);
236 ifc->set |= IFC_ADMIN;
237 ifc->admin = (value->v.integer == 1) ? 1 : 0;
238
239 return (SNMP_ERR_NOERROR);
240
241 case SNMP_OP_ROLLBACK:
242 case SNMP_OP_COMMIT:
243 return (SNMP_ERR_NOERROR);
244 }
245
246 if (ifp->mibtick < this_tick)
247 (void)mib_fetch_ifmib(ifp);
248
249 ret = SNMP_ERR_NOERROR;
250 switch (value->var.subs[sub - 1]) {
251
252 case LEAF_ifIndex:
253 value->v.integer = ifp->index;
254 break;
255
256 case LEAF_ifDescr:
257 ret = string_get(value, ifp->descr, -1);
258 break;
259
260 case LEAF_ifType:
261 value->v.integer = ifp->mib.ifmd_data.ifi_type;
262 break;
263
264 case LEAF_ifMtu:
265 value->v.integer = ifp->mib.ifmd_data.ifi_mtu;
266 break;
267
268 case LEAF_ifSpeed:
269 value->v.integer = ifp->mib.ifmd_data.ifi_baudrate;
270 break;
271
272 case LEAF_ifPhysAddress:
273 ret = string_get(value, ifp->physaddr,
274 ifp->physaddrlen);
275 break;
276
277 case LEAF_ifAdminStatus:
278 value->v.integer =
279 (ifp->mib.ifmd_flags & IFF_UP) ? 1 : 2;
280 break;
281
282 case LEAF_ifOperStatus:
283 value->v.integer =
284 (ifp->mib.ifmd_flags & IFF_RUNNING) ? 1 : 2;
283 /*
284 * According to RFC 2863 the state should be Up if the
285 * interface is ready to transmit packets. We takes this to
286 * mean that the interface should be running and should have
287 * a carrier. If it is running and has no carrier we interpret
288 * this as 'waiting for an external event' (plugging in the
289 * cable) and hence return 'dormant'.
290 */
291 if (ifp->mib.ifmd_flags & IFF_RUNNING) {
292 if (ifp->mib.ifmd_data.ifi_link_state ==
293 LINK_STATE_DOWN)
294 value->v.integer = 5; /* state dormant */
295 else
296 value->v.integer = 1; /* state up */
297 } else
298 value->v.integer = 2; /* state down */
285 break;
286
287 case LEAF_ifLastChange:
288 value->v.uint32 =
289 ticks_get_timeval(&ifp->mib.ifmd_data.ifi_lastchange);
290 break;
291
292 case LEAF_ifInOctets:
293 value->v.uint32 = ifp->mib.ifmd_data.ifi_ibytes;
294 break;
295
296 case LEAF_ifInUcastPkts:
297 value->v.uint32 = ifp->mib.ifmd_data.ifi_ipackets -
298 ifp->mib.ifmd_data.ifi_imcasts;
299 break;
300
301 case LEAF_ifInNUcastPkts:
302 value->v.uint32 = ifp->mib.ifmd_data.ifi_imcasts;
303 break;
304
305 case LEAF_ifInDiscards:
306 value->v.uint32 = ifp->mib.ifmd_data.ifi_iqdrops;
307 break;
308
309 case LEAF_ifInErrors:
310 value->v.uint32 = ifp->mib.ifmd_data.ifi_ierrors;
311 break;
312
313 case LEAF_ifInUnknownProtos:
314 value->v.uint32 = ifp->mib.ifmd_data.ifi_noproto;
315 break;
316
317 case LEAF_ifOutOctets:
318 value->v.uint32 = ifp->mib.ifmd_data.ifi_obytes;
319 break;
320
321 case LEAF_ifOutUcastPkts:
322 value->v.uint32 = ifp->mib.ifmd_data.ifi_opackets -
323 ifp->mib.ifmd_data.ifi_omcasts;
324 break;
325
326 case LEAF_ifOutNUcastPkts:
327 value->v.uint32 = ifp->mib.ifmd_data.ifi_omcasts;
328 break;
329
330 case LEAF_ifOutDiscards:
331 value->v.uint32 = ifp->mib.ifmd_snd_drops;
332 break;
333
334 case LEAF_ifOutErrors:
335 value->v.uint32 = ifp->mib.ifmd_data.ifi_oerrors;
336 break;
337
338 case LEAF_ifOutQLen:
339 value->v.uint32 = ifp->mib.ifmd_snd_len;
340 break;
341
342 case LEAF_ifSpecific:
343 value->v.oid = ifp->spec_oid;
344 break;
345 }
346 return (SNMP_ERR_NOERROR);
347}
348
349/*
350 * IfXtable entry
351 */
352int
353op_ifxtable(struct snmp_context *ctx, struct snmp_value *value,
354 u_int sub, u_int iidx __unused, enum snmp_op op)
355{
356 struct mibif *ifp = NULL;
357 int ret;
358 struct ifchange *ifc;
359 struct asn_oid idx;
360
361 switch (op) {
362
363 again:
364 if (op != SNMP_OP_GETNEXT)
365 return (SNMP_ERR_NOSUCHNAME);
366 /* FALLTHROUGH */
367
368 case SNMP_OP_GETNEXT:
369 if ((ifp = NEXT_OBJECT_INT(&mibif_list, &value->var, sub)) == NULL)
370 return (SNMP_ERR_NOSUCHNAME);
371 value->var.len = sub + 1;
372 value->var.subs[sub] = ifp->index;
373 break;
374
375 case SNMP_OP_GET:
376 if (value->var.len - sub != 1)
377 return (SNMP_ERR_NOSUCHNAME);
378 if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)
379 return (SNMP_ERR_NOSUCHNAME);
380 break;
381
382 case SNMP_OP_SET:
383 if (value->var.len - sub != 1)
384 return (SNMP_ERR_NO_CREATION);
385 if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)
386 return (SNMP_ERR_NO_CREATION);
387
388 idx.len = 1;
389 idx.subs[0] = ifp->index;
390
391 if ((ifc = (struct ifchange *)snmp_dep_lookup(ctx,
392 &oid_ifTable, &idx, sizeof(*ifc), ifchange_func)) == NULL)
393 return (SNMP_ERR_RES_UNAVAIL);
394 ifc->ifindex = ifp->index;
395
396 switch (value->var.subs[sub - 1]) {
397
398 case LEAF_ifLinkUpDownTrapEnable:
399 if (value->v.integer != 1 && value->v.integer != 2)
400 return (SNMP_ERR_WRONG_VALUE);
401 if (ifc->set & IFC_TRAPS)
402 return (SNMP_ERR_INCONS_VALUE);
403 ifc->set |= IFC_TRAPS;
404 ifc->traps = (value->v.integer == 1) ? 1 : 0;
405 return (SNMP_ERR_NOERROR);
406
407 case LEAF_ifPromiscuousMode:
408 if (value->v.integer != 1 && value->v.integer != 2)
409 return (SNMP_ERR_WRONG_VALUE);
410 if (ifc->set & IFC_PROMISC)
411 return (SNMP_ERR_INCONS_VALUE);
412 ifc->set |= IFC_PROMISC;
413 ifc->promisc = (value->v.integer == 1) ? 1 : 0;
414 return (SNMP_ERR_NOERROR);
415 }
416 return (SNMP_ERR_NOT_WRITEABLE);
417
418 case SNMP_OP_ROLLBACK:
419 case SNMP_OP_COMMIT:
420 return (SNMP_ERR_NOERROR);
421 }
422
423 if (ifp->mibtick < this_tick)
424 (void)mib_fetch_ifmib(ifp);
425
426 ret = SNMP_ERR_NOERROR;
427 switch (value->var.subs[sub - 1]) {
428
429 case LEAF_ifName:
430 ret = string_get(value, ifp->name, -1);
431 break;
432
433 case LEAF_ifInMulticastPkts:
434 value->v.uint32 = ifp->mib.ifmd_data.ifi_imcasts;
435 break;
436
437 case LEAF_ifInBroadcastPkts:
438 value->v.uint32 = 0;
439 break;
440
441 case LEAF_ifOutMulticastPkts:
442 value->v.uint32 = ifp->mib.ifmd_data.ifi_omcasts;
443 break;
444
445 case LEAF_ifOutBroadcastPkts:
446 value->v.uint32 = 0;
447 break;
448
449 case LEAF_ifHCInOctets:
450 if (!(ifp->flags & MIBIF_HIGHSPEED))
451 goto again;
452 value->v.counter64 = ifp->hc_inoctets;
453 break;
454
455 case LEAF_ifHCInUcastPkts:
456 if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
457 goto again;
458 value->v.counter64 = ifp->hc_ipackets - ifp->hc_imcasts;
459 break;
460
461 case LEAF_ifHCInMulticastPkts:
462 if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
463 goto again;
464 value->v.counter64 = ifp->hc_imcasts;
465 break;
466
467 case LEAF_ifHCInBroadcastPkts:
468 if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
469 goto again;
470 value->v.counter64 = 0;
471 break;
472
473 case LEAF_ifHCOutOctets:
474 if (!(ifp->flags & MIBIF_HIGHSPEED))
475 goto again;
476 value->v.counter64 = ifp->hc_outoctets;
477 break;
478
479 case LEAF_ifHCOutUcastPkts:
480 if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
481 goto again;
482 value->v.counter64 = ifp->hc_opackets - ifp->hc_omcasts;
483 break;
484
485 case LEAF_ifHCOutMulticastPkts:
486 if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
487 goto again;
488 value->v.counter64 = ifp->hc_omcasts;
489 break;
490
491 case LEAF_ifHCOutBroadcastPkts:
492 if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
493 goto again;
494 value->v.counter64 = 0;
495 break;
496
497 case LEAF_ifLinkUpDownTrapEnable:
498 value->v.integer = ifp->trap_enable ? 1 : 2;
499 break;
500
501 case LEAF_ifHighSpeed:
502 value->v.integer =
503 (ifp->mib.ifmd_data.ifi_baudrate + 499999) / 1000000;
504 break;
505
506 case LEAF_ifPromiscuousMode:
507 value->v.integer =
508 (ifp->mib.ifmd_flags & IFF_PROMISC) ? 1 : 2;
509 break;
510
511 case LEAF_ifConnectorPresent:
512 value->v.integer = ifp->has_connector ? 1 : 2;
513 break;
514
515 case LEAF_ifAlias:
516 ret = string_get(value, "", -1);
517 break;
518
519 case LEAF_ifCounterDiscontinuityTime:
520 if (ifp->counter_disc > start_tick)
521 value->v.uint32 = ifp->counter_disc - start_tick;
522 else
523 value->v.uint32 = 0;
524 break;
525 }
526 return (ret);
527}
299 break;
300
301 case LEAF_ifLastChange:
302 value->v.uint32 =
303 ticks_get_timeval(&ifp->mib.ifmd_data.ifi_lastchange);
304 break;
305
306 case LEAF_ifInOctets:
307 value->v.uint32 = ifp->mib.ifmd_data.ifi_ibytes;
308 break;
309
310 case LEAF_ifInUcastPkts:
311 value->v.uint32 = ifp->mib.ifmd_data.ifi_ipackets -
312 ifp->mib.ifmd_data.ifi_imcasts;
313 break;
314
315 case LEAF_ifInNUcastPkts:
316 value->v.uint32 = ifp->mib.ifmd_data.ifi_imcasts;
317 break;
318
319 case LEAF_ifInDiscards:
320 value->v.uint32 = ifp->mib.ifmd_data.ifi_iqdrops;
321 break;
322
323 case LEAF_ifInErrors:
324 value->v.uint32 = ifp->mib.ifmd_data.ifi_ierrors;
325 break;
326
327 case LEAF_ifInUnknownProtos:
328 value->v.uint32 = ifp->mib.ifmd_data.ifi_noproto;
329 break;
330
331 case LEAF_ifOutOctets:
332 value->v.uint32 = ifp->mib.ifmd_data.ifi_obytes;
333 break;
334
335 case LEAF_ifOutUcastPkts:
336 value->v.uint32 = ifp->mib.ifmd_data.ifi_opackets -
337 ifp->mib.ifmd_data.ifi_omcasts;
338 break;
339
340 case LEAF_ifOutNUcastPkts:
341 value->v.uint32 = ifp->mib.ifmd_data.ifi_omcasts;
342 break;
343
344 case LEAF_ifOutDiscards:
345 value->v.uint32 = ifp->mib.ifmd_snd_drops;
346 break;
347
348 case LEAF_ifOutErrors:
349 value->v.uint32 = ifp->mib.ifmd_data.ifi_oerrors;
350 break;
351
352 case LEAF_ifOutQLen:
353 value->v.uint32 = ifp->mib.ifmd_snd_len;
354 break;
355
356 case LEAF_ifSpecific:
357 value->v.oid = ifp->spec_oid;
358 break;
359 }
360 return (SNMP_ERR_NOERROR);
361}
362
363/*
364 * IfXtable entry
365 */
366int
367op_ifxtable(struct snmp_context *ctx, struct snmp_value *value,
368 u_int sub, u_int iidx __unused, enum snmp_op op)
369{
370 struct mibif *ifp = NULL;
371 int ret;
372 struct ifchange *ifc;
373 struct asn_oid idx;
374
375 switch (op) {
376
377 again:
378 if (op != SNMP_OP_GETNEXT)
379 return (SNMP_ERR_NOSUCHNAME);
380 /* FALLTHROUGH */
381
382 case SNMP_OP_GETNEXT:
383 if ((ifp = NEXT_OBJECT_INT(&mibif_list, &value->var, sub)) == NULL)
384 return (SNMP_ERR_NOSUCHNAME);
385 value->var.len = sub + 1;
386 value->var.subs[sub] = ifp->index;
387 break;
388
389 case SNMP_OP_GET:
390 if (value->var.len - sub != 1)
391 return (SNMP_ERR_NOSUCHNAME);
392 if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)
393 return (SNMP_ERR_NOSUCHNAME);
394 break;
395
396 case SNMP_OP_SET:
397 if (value->var.len - sub != 1)
398 return (SNMP_ERR_NO_CREATION);
399 if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)
400 return (SNMP_ERR_NO_CREATION);
401
402 idx.len = 1;
403 idx.subs[0] = ifp->index;
404
405 if ((ifc = (struct ifchange *)snmp_dep_lookup(ctx,
406 &oid_ifTable, &idx, sizeof(*ifc), ifchange_func)) == NULL)
407 return (SNMP_ERR_RES_UNAVAIL);
408 ifc->ifindex = ifp->index;
409
410 switch (value->var.subs[sub - 1]) {
411
412 case LEAF_ifLinkUpDownTrapEnable:
413 if (value->v.integer != 1 && value->v.integer != 2)
414 return (SNMP_ERR_WRONG_VALUE);
415 if (ifc->set & IFC_TRAPS)
416 return (SNMP_ERR_INCONS_VALUE);
417 ifc->set |= IFC_TRAPS;
418 ifc->traps = (value->v.integer == 1) ? 1 : 0;
419 return (SNMP_ERR_NOERROR);
420
421 case LEAF_ifPromiscuousMode:
422 if (value->v.integer != 1 && value->v.integer != 2)
423 return (SNMP_ERR_WRONG_VALUE);
424 if (ifc->set & IFC_PROMISC)
425 return (SNMP_ERR_INCONS_VALUE);
426 ifc->set |= IFC_PROMISC;
427 ifc->promisc = (value->v.integer == 1) ? 1 : 0;
428 return (SNMP_ERR_NOERROR);
429 }
430 return (SNMP_ERR_NOT_WRITEABLE);
431
432 case SNMP_OP_ROLLBACK:
433 case SNMP_OP_COMMIT:
434 return (SNMP_ERR_NOERROR);
435 }
436
437 if (ifp->mibtick < this_tick)
438 (void)mib_fetch_ifmib(ifp);
439
440 ret = SNMP_ERR_NOERROR;
441 switch (value->var.subs[sub - 1]) {
442
443 case LEAF_ifName:
444 ret = string_get(value, ifp->name, -1);
445 break;
446
447 case LEAF_ifInMulticastPkts:
448 value->v.uint32 = ifp->mib.ifmd_data.ifi_imcasts;
449 break;
450
451 case LEAF_ifInBroadcastPkts:
452 value->v.uint32 = 0;
453 break;
454
455 case LEAF_ifOutMulticastPkts:
456 value->v.uint32 = ifp->mib.ifmd_data.ifi_omcasts;
457 break;
458
459 case LEAF_ifOutBroadcastPkts:
460 value->v.uint32 = 0;
461 break;
462
463 case LEAF_ifHCInOctets:
464 if (!(ifp->flags & MIBIF_HIGHSPEED))
465 goto again;
466 value->v.counter64 = ifp->hc_inoctets;
467 break;
468
469 case LEAF_ifHCInUcastPkts:
470 if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
471 goto again;
472 value->v.counter64 = ifp->hc_ipackets - ifp->hc_imcasts;
473 break;
474
475 case LEAF_ifHCInMulticastPkts:
476 if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
477 goto again;
478 value->v.counter64 = ifp->hc_imcasts;
479 break;
480
481 case LEAF_ifHCInBroadcastPkts:
482 if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
483 goto again;
484 value->v.counter64 = 0;
485 break;
486
487 case LEAF_ifHCOutOctets:
488 if (!(ifp->flags & MIBIF_HIGHSPEED))
489 goto again;
490 value->v.counter64 = ifp->hc_outoctets;
491 break;
492
493 case LEAF_ifHCOutUcastPkts:
494 if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
495 goto again;
496 value->v.counter64 = ifp->hc_opackets - ifp->hc_omcasts;
497 break;
498
499 case LEAF_ifHCOutMulticastPkts:
500 if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
501 goto again;
502 value->v.counter64 = ifp->hc_omcasts;
503 break;
504
505 case LEAF_ifHCOutBroadcastPkts:
506 if (!(ifp->flags & (MIBIF_VERYHIGHSPEED|MIBIF_HIGHSPEED)))
507 goto again;
508 value->v.counter64 = 0;
509 break;
510
511 case LEAF_ifLinkUpDownTrapEnable:
512 value->v.integer = ifp->trap_enable ? 1 : 2;
513 break;
514
515 case LEAF_ifHighSpeed:
516 value->v.integer =
517 (ifp->mib.ifmd_data.ifi_baudrate + 499999) / 1000000;
518 break;
519
520 case LEAF_ifPromiscuousMode:
521 value->v.integer =
522 (ifp->mib.ifmd_flags & IFF_PROMISC) ? 1 : 2;
523 break;
524
525 case LEAF_ifConnectorPresent:
526 value->v.integer = ifp->has_connector ? 1 : 2;
527 break;
528
529 case LEAF_ifAlias:
530 ret = string_get(value, "", -1);
531 break;
532
533 case LEAF_ifCounterDiscontinuityTime:
534 if (ifp->counter_disc > start_tick)
535 value->v.uint32 = ifp->counter_disc - start_tick;
536 else
537 value->v.uint32 = 0;
538 break;
539 }
540 return (ret);
541}