Deleted Added
full compact
bridge_port.c (164997) bridge_port.c (165046)
1/*-
2 * Copyright (c) 2006 Shteryana Shopova <syrinx@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * Bridge MIB implementation for SNMPd.
27 * Bridge ports.
28 *
1/*-
2 * Copyright (c) 2006 Shteryana Shopova <syrinx@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * Bridge MIB implementation for SNMPd.
27 * Bridge ports.
28 *
29 * $FreeBSD: head/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_port.c 164997 2006-12-07 22:36:17Z syrinx $
29 * $FreeBSD: head/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_port.c 165046 2006-12-09 20:58:26Z syrinx $
30 */
31
32#include <sys/queue.h>
33#include <sys/socket.h>
34#include <sys/types.h>
35
36#include <net/ethernet.h>
37#include <net/if.h>
38#include <net/if_mib.h>
39
40#include <assert.h>
41#include <errno.h>
42#include <stdarg.h>
43#include <string.h>
44#include <stdlib.h>
45#include <syslog.h>
46
47#include <bsnmp/snmpmod.h>
48#include <bsnmp/snmp_mibII.h>
49
50#include "bridge_tree.h"
51#include "bridge_snmp.h"
52
53TAILQ_HEAD(bridge_ports, bridge_port);
54
55/*
56 * Free the bridge base ports list.
57 */
58static void
59bridge_ports_free(struct bridge_ports *headp)
60{
61 struct bridge_port *bp;
62
63 while ((bp = TAILQ_FIRST(headp)) != NULL) {
64 TAILQ_REMOVE(headp, bp, b_p);
65 free(bp);
66 }
67}
68
69/*
70 * Free the bridge base ports from the base ports list,
71 * members of a specified bridge interface only.
72 */
73static void
74bridge_port_memif_free(struct bridge_ports *headp,
75 struct bridge_if *bif)
76{
77 struct bridge_port *bp;
78
79 while (bif->f_bp != NULL && bif->sysindex == bif->f_bp->sysindex) {
80 bp = TAILQ_NEXT(bif->f_bp, b_p);
81 TAILQ_REMOVE(headp, bif->f_bp, b_p);
82 free(bif->f_bp);
83 bif->f_bp = bp;
84 }
85}
86
87/*
88 * Insert a port entry in the base port TAILQ starting to search
89 * for its place from the position of the first bridge port for the bridge
90 * interface. Update the first bridge port if neccessary.
91 */
92static void
93bridge_port_insert_at(struct bridge_ports *headp,
94 struct bridge_port *bp, struct bridge_port **f_bp)
95{
96 struct bridge_port *t1;
97
98 assert(f_bp != NULL);
99
100 for (t1 = *f_bp;
101 t1 != NULL && bp->sysindex == t1->sysindex;
102 t1 = TAILQ_NEXT(t1, b_p)) {
103 if (bp->if_idx < t1->if_idx) {
104 TAILQ_INSERT_BEFORE(t1, bp, b_p);
105 if (*f_bp == t1)
106 *f_bp = bp;
107 return;
108 }
109 }
110
111 /*
112 * Handle the case when our first port was actually the
113 * last element of the TAILQ.
114 */
115 if (t1 == NULL)
116 TAILQ_INSERT_TAIL(headp, bp, b_p);
117 else
118 TAILQ_INSERT_BEFORE(t1, bp, b_p);
119}
120
121/*
122 * Find a port entry's possition in the ports list according
123 * to it's parent bridge interface name. Returns a NULL if
124 * we should be at the TAILQ head, otherwise the entry after
125 * which we should be inserted.
126 */
127static struct bridge_port *
128bridge_port_find_pos(struct bridge_ports *headp, uint32_t b_idx)
129{
130 uint32_t t_idx;
131 struct bridge_port *t1;
132
133 if ((t1 = TAILQ_FIRST(headp)) == NULL ||
134 bridge_compare_sysidx(b_idx, t1->sysindex) < 0)
135 return (NULL);
136
137 t_idx = t1->sysindex;
138
139 for (t1 = TAILQ_NEXT(t1, b_p); t1 != NULL; t1 = TAILQ_NEXT(t1, b_p)) {
140 if (t1->sysindex != t_idx) {
141 if (bridge_compare_sysidx(b_idx, t1->sysindex) < 0)
142 return (TAILQ_PREV(t1, bridge_ports, b_p));
143 else
144 t_idx = t1->sysindex;
145 }
146 }
147
148 if (t1 == NULL)
149 t1 = TAILQ_LAST(headp, bridge_ports);
150
151 return (t1);
152}
153
154/*
155 * Insert a bridge member interface in the ports TAILQ.
156 */
157static void
158bridge_port_memif_insert(struct bridge_ports *headp,
159 struct bridge_port *bp, struct bridge_port **f_bp)
160{
161 struct bridge_port *temp;
162
163 if (*f_bp != NULL)
164 bridge_port_insert_at(headp, bp, f_bp);
165 else {
166 temp = bridge_port_find_pos(headp, bp->sysindex);
167
168 if (temp == NULL)
169 TAILQ_INSERT_HEAD(headp, bp, b_p);
170 else
171 TAILQ_INSERT_AFTER(headp, temp, bp, b_p);
172 *f_bp = bp;
173 }
174}
175
176/* The global ports list. */
177static struct bridge_ports bridge_ports = TAILQ_HEAD_INITIALIZER(bridge_ports);
178static time_t ports_list_age;
179
180void
181bridge_ports_update_listage(void)
182{
183 ports_list_age = time(NULL);
184}
185
186void
187bridge_ports_fini(void)
188{
189 bridge_ports_free(&bridge_ports);
190}
191
192void
193bridge_members_free(struct bridge_if *bif)
194{
195 bridge_port_memif_free(&bridge_ports, bif);
196}
197
198/*
199 * Find the first port in the ports list.
200 */
201static struct bridge_port *
202bridge_port_first(void)
203{
204 return (TAILQ_FIRST(&bridge_ports));
205}
206
207/*
208 * Find the next port in the ports list.
209 */
210static struct bridge_port *
211bridge_port_next(struct bridge_port *bp)
212{
213 return (TAILQ_NEXT(bp, b_p));
214}
215
216/*
217 * Find the first member of the specified bridge interface.
218 */
219struct bridge_port *
220bridge_port_bif_first(struct bridge_if *bif)
221{
222 return (bif->f_bp);
223}
224
225/*
226 * Find the next member of the specified bridge interface.
227 */
228struct bridge_port *
229bridge_port_bif_next(struct bridge_port *bp)
230{
231 struct bridge_port *bp_next;
232
233 if ((bp_next = TAILQ_NEXT(bp, b_p)) == NULL ||
234 bp_next->sysindex != bp->sysindex)
235 return (NULL);
236
237 return (bp_next);
238}
239
240/*
241 * Remove a bridge port from the ports list.
242 */
243void
244bridge_port_remove(struct bridge_port *bp, struct bridge_if *bif)
245{
246 if (bif->f_bp == bp)
247 bif->f_bp = bridge_port_bif_next(bp);
248
249 TAILQ_REMOVE(&bridge_ports, bp, b_p);
250 free(bp);
251}
252
253/*
254 * Allocate memory for a new bridge port and insert it
255 * in the base ports list. Return a pointer to the port's
256 * structure in case we want to do anything else with it.
257 */
258struct bridge_port *
259bridge_new_port(struct mibif *mif, struct bridge_if *bif)
260{
261 struct bridge_port *bp;
262
263 if ((bp = (struct bridge_port *) malloc(sizeof(*bp))) == NULL) {
264 syslog(LOG_ERR, "bridge new member: failed: %s",
265 strerror(errno));
266 return (NULL);
267 }
268
269 bzero(bp, sizeof(*bp));
270
271 bp->sysindex = bif->sysindex;
272 bp->if_idx = mif->index;
273 bp->port_no = mif->sysindex;
274 strlcpy(bp->p_name, mif->name, IFNAMSIZ);
275 bp->circuit = oid_zeroDotZero;
276
277 /*
278 * Initialize all rstpMib specific values to false/default.
279 * These will be set to their true values later if the bridge
280 * supports RSTP.
281 */
282 bp->proto_migr = TruthValue_false;
283 bp->admin_edge = TruthValue_false;
284 bp->oper_edge = TruthValue_false;
285 bp->oper_p2p = TruthValue_false;
286 bp->admin_p2p = StpPortAdminPointToPointType_auto;
287
288 bridge_port_memif_insert(&bridge_ports, bp, &(bif->f_bp));
289
290 return (bp);
291}
292
293/*
294 * Update our info from the corresponding mibII interface info.
295 */
296void
297bridge_port_getinfo_mibif(struct mibif *m_if, struct bridge_port *bp)
298{
299 bp->max_info = m_if->mib.ifmd_data.ifi_mtu;
300 bp->in_frames = m_if->mib.ifmd_data.ifi_ipackets;
301 bp->out_frames = m_if->mib.ifmd_data.ifi_opackets;
302 bp->in_drops = m_if->mib.ifmd_data.ifi_iqdrops;
303}
304
305/*
306 * Find a port, whose SNMP's mibII ifIndex matches one of the ports,
307 * members of the specified bridge interface.
308 */
309struct bridge_port *
310bridge_port_find(int32_t if_idx, struct bridge_if *bif)
311{
312 struct bridge_port *bp;
313
314 for (bp = bif->f_bp; bp != NULL; bp = TAILQ_NEXT(bp, b_p)) {
315 if (bp->sysindex != bif->sysindex) {
316 bp = NULL;
317 break;
318 }
319
320 if (bp->if_idx == if_idx)
321 break;
322 }
323
324 return (bp);
325}
326
327void
328bridge_ports_dump(struct bridge_if *bif)
329{
330 struct bridge_port *bp;
331
332 for (bp = bridge_port_bif_first(bif); bp != NULL;
333 bp = bridge_port_bif_next(bp)) {
334 syslog(LOG_ERR, "memif - %s, index - %d",
335 bp->p_name, bp->port_no);
336 }
337}
338
339/*
340 * RFC4188 specifics.
341 */
342int
343op_dot1d_base_port(struct snmp_context *c __unused, struct snmp_value *val,
344 uint sub, uint iidx __unused, enum snmp_op op)
345{
346 struct bridge_if *bif;
347 struct bridge_port *bp;
348
349 if ((bif = bridge_get_default()) == NULL)
350 return (SNMP_ERR_NOSUCHNAME);
351
352 if (time(NULL) - bif->ports_age > bridge_get_data_maxage() &&
353 bridge_update_memif(bif) <= 0)
354 return (SNMP_ERR_NOSUCHNAME);
355
30 */
31
32#include <sys/queue.h>
33#include <sys/socket.h>
34#include <sys/types.h>
35
36#include <net/ethernet.h>
37#include <net/if.h>
38#include <net/if_mib.h>
39
40#include <assert.h>
41#include <errno.h>
42#include <stdarg.h>
43#include <string.h>
44#include <stdlib.h>
45#include <syslog.h>
46
47#include <bsnmp/snmpmod.h>
48#include <bsnmp/snmp_mibII.h>
49
50#include "bridge_tree.h"
51#include "bridge_snmp.h"
52
53TAILQ_HEAD(bridge_ports, bridge_port);
54
55/*
56 * Free the bridge base ports list.
57 */
58static void
59bridge_ports_free(struct bridge_ports *headp)
60{
61 struct bridge_port *bp;
62
63 while ((bp = TAILQ_FIRST(headp)) != NULL) {
64 TAILQ_REMOVE(headp, bp, b_p);
65 free(bp);
66 }
67}
68
69/*
70 * Free the bridge base ports from the base ports list,
71 * members of a specified bridge interface only.
72 */
73static void
74bridge_port_memif_free(struct bridge_ports *headp,
75 struct bridge_if *bif)
76{
77 struct bridge_port *bp;
78
79 while (bif->f_bp != NULL && bif->sysindex == bif->f_bp->sysindex) {
80 bp = TAILQ_NEXT(bif->f_bp, b_p);
81 TAILQ_REMOVE(headp, bif->f_bp, b_p);
82 free(bif->f_bp);
83 bif->f_bp = bp;
84 }
85}
86
87/*
88 * Insert a port entry in the base port TAILQ starting to search
89 * for its place from the position of the first bridge port for the bridge
90 * interface. Update the first bridge port if neccessary.
91 */
92static void
93bridge_port_insert_at(struct bridge_ports *headp,
94 struct bridge_port *bp, struct bridge_port **f_bp)
95{
96 struct bridge_port *t1;
97
98 assert(f_bp != NULL);
99
100 for (t1 = *f_bp;
101 t1 != NULL && bp->sysindex == t1->sysindex;
102 t1 = TAILQ_NEXT(t1, b_p)) {
103 if (bp->if_idx < t1->if_idx) {
104 TAILQ_INSERT_BEFORE(t1, bp, b_p);
105 if (*f_bp == t1)
106 *f_bp = bp;
107 return;
108 }
109 }
110
111 /*
112 * Handle the case when our first port was actually the
113 * last element of the TAILQ.
114 */
115 if (t1 == NULL)
116 TAILQ_INSERT_TAIL(headp, bp, b_p);
117 else
118 TAILQ_INSERT_BEFORE(t1, bp, b_p);
119}
120
121/*
122 * Find a port entry's possition in the ports list according
123 * to it's parent bridge interface name. Returns a NULL if
124 * we should be at the TAILQ head, otherwise the entry after
125 * which we should be inserted.
126 */
127static struct bridge_port *
128bridge_port_find_pos(struct bridge_ports *headp, uint32_t b_idx)
129{
130 uint32_t t_idx;
131 struct bridge_port *t1;
132
133 if ((t1 = TAILQ_FIRST(headp)) == NULL ||
134 bridge_compare_sysidx(b_idx, t1->sysindex) < 0)
135 return (NULL);
136
137 t_idx = t1->sysindex;
138
139 for (t1 = TAILQ_NEXT(t1, b_p); t1 != NULL; t1 = TAILQ_NEXT(t1, b_p)) {
140 if (t1->sysindex != t_idx) {
141 if (bridge_compare_sysidx(b_idx, t1->sysindex) < 0)
142 return (TAILQ_PREV(t1, bridge_ports, b_p));
143 else
144 t_idx = t1->sysindex;
145 }
146 }
147
148 if (t1 == NULL)
149 t1 = TAILQ_LAST(headp, bridge_ports);
150
151 return (t1);
152}
153
154/*
155 * Insert a bridge member interface in the ports TAILQ.
156 */
157static void
158bridge_port_memif_insert(struct bridge_ports *headp,
159 struct bridge_port *bp, struct bridge_port **f_bp)
160{
161 struct bridge_port *temp;
162
163 if (*f_bp != NULL)
164 bridge_port_insert_at(headp, bp, f_bp);
165 else {
166 temp = bridge_port_find_pos(headp, bp->sysindex);
167
168 if (temp == NULL)
169 TAILQ_INSERT_HEAD(headp, bp, b_p);
170 else
171 TAILQ_INSERT_AFTER(headp, temp, bp, b_p);
172 *f_bp = bp;
173 }
174}
175
176/* The global ports list. */
177static struct bridge_ports bridge_ports = TAILQ_HEAD_INITIALIZER(bridge_ports);
178static time_t ports_list_age;
179
180void
181bridge_ports_update_listage(void)
182{
183 ports_list_age = time(NULL);
184}
185
186void
187bridge_ports_fini(void)
188{
189 bridge_ports_free(&bridge_ports);
190}
191
192void
193bridge_members_free(struct bridge_if *bif)
194{
195 bridge_port_memif_free(&bridge_ports, bif);
196}
197
198/*
199 * Find the first port in the ports list.
200 */
201static struct bridge_port *
202bridge_port_first(void)
203{
204 return (TAILQ_FIRST(&bridge_ports));
205}
206
207/*
208 * Find the next port in the ports list.
209 */
210static struct bridge_port *
211bridge_port_next(struct bridge_port *bp)
212{
213 return (TAILQ_NEXT(bp, b_p));
214}
215
216/*
217 * Find the first member of the specified bridge interface.
218 */
219struct bridge_port *
220bridge_port_bif_first(struct bridge_if *bif)
221{
222 return (bif->f_bp);
223}
224
225/*
226 * Find the next member of the specified bridge interface.
227 */
228struct bridge_port *
229bridge_port_bif_next(struct bridge_port *bp)
230{
231 struct bridge_port *bp_next;
232
233 if ((bp_next = TAILQ_NEXT(bp, b_p)) == NULL ||
234 bp_next->sysindex != bp->sysindex)
235 return (NULL);
236
237 return (bp_next);
238}
239
240/*
241 * Remove a bridge port from the ports list.
242 */
243void
244bridge_port_remove(struct bridge_port *bp, struct bridge_if *bif)
245{
246 if (bif->f_bp == bp)
247 bif->f_bp = bridge_port_bif_next(bp);
248
249 TAILQ_REMOVE(&bridge_ports, bp, b_p);
250 free(bp);
251}
252
253/*
254 * Allocate memory for a new bridge port and insert it
255 * in the base ports list. Return a pointer to the port's
256 * structure in case we want to do anything else with it.
257 */
258struct bridge_port *
259bridge_new_port(struct mibif *mif, struct bridge_if *bif)
260{
261 struct bridge_port *bp;
262
263 if ((bp = (struct bridge_port *) malloc(sizeof(*bp))) == NULL) {
264 syslog(LOG_ERR, "bridge new member: failed: %s",
265 strerror(errno));
266 return (NULL);
267 }
268
269 bzero(bp, sizeof(*bp));
270
271 bp->sysindex = bif->sysindex;
272 bp->if_idx = mif->index;
273 bp->port_no = mif->sysindex;
274 strlcpy(bp->p_name, mif->name, IFNAMSIZ);
275 bp->circuit = oid_zeroDotZero;
276
277 /*
278 * Initialize all rstpMib specific values to false/default.
279 * These will be set to their true values later if the bridge
280 * supports RSTP.
281 */
282 bp->proto_migr = TruthValue_false;
283 bp->admin_edge = TruthValue_false;
284 bp->oper_edge = TruthValue_false;
285 bp->oper_p2p = TruthValue_false;
286 bp->admin_p2p = StpPortAdminPointToPointType_auto;
287
288 bridge_port_memif_insert(&bridge_ports, bp, &(bif->f_bp));
289
290 return (bp);
291}
292
293/*
294 * Update our info from the corresponding mibII interface info.
295 */
296void
297bridge_port_getinfo_mibif(struct mibif *m_if, struct bridge_port *bp)
298{
299 bp->max_info = m_if->mib.ifmd_data.ifi_mtu;
300 bp->in_frames = m_if->mib.ifmd_data.ifi_ipackets;
301 bp->out_frames = m_if->mib.ifmd_data.ifi_opackets;
302 bp->in_drops = m_if->mib.ifmd_data.ifi_iqdrops;
303}
304
305/*
306 * Find a port, whose SNMP's mibII ifIndex matches one of the ports,
307 * members of the specified bridge interface.
308 */
309struct bridge_port *
310bridge_port_find(int32_t if_idx, struct bridge_if *bif)
311{
312 struct bridge_port *bp;
313
314 for (bp = bif->f_bp; bp != NULL; bp = TAILQ_NEXT(bp, b_p)) {
315 if (bp->sysindex != bif->sysindex) {
316 bp = NULL;
317 break;
318 }
319
320 if (bp->if_idx == if_idx)
321 break;
322 }
323
324 return (bp);
325}
326
327void
328bridge_ports_dump(struct bridge_if *bif)
329{
330 struct bridge_port *bp;
331
332 for (bp = bridge_port_bif_first(bif); bp != NULL;
333 bp = bridge_port_bif_next(bp)) {
334 syslog(LOG_ERR, "memif - %s, index - %d",
335 bp->p_name, bp->port_no);
336 }
337}
338
339/*
340 * RFC4188 specifics.
341 */
342int
343op_dot1d_base_port(struct snmp_context *c __unused, struct snmp_value *val,
344 uint sub, uint iidx __unused, enum snmp_op op)
345{
346 struct bridge_if *bif;
347 struct bridge_port *bp;
348
349 if ((bif = bridge_get_default()) == NULL)
350 return (SNMP_ERR_NOSUCHNAME);
351
352 if (time(NULL) - bif->ports_age > bridge_get_data_maxage() &&
353 bridge_update_memif(bif) <= 0)
354 return (SNMP_ERR_NOSUCHNAME);
355
356 bp = NULL; /* Make the compiler happy. */
357 switch (op) {
358 case SNMP_OP_GET:
359 if (val->var.len - sub != 1)
360 return (SNMP_ERR_NOSUCHNAME);
361 if ((bp = bridge_port_find(val->var.subs[sub],
362 bif)) == NULL)
363 return (SNMP_ERR_NOSUCHNAME);
364 break;
365
366 case SNMP_OP_GETNEXT:
367 if (val->var.len - sub == 0) {
368 if ((bp = bridge_port_bif_first(bif)) == NULL)
369 return (SNMP_ERR_NOSUCHNAME);
370 } else {
371 if ((bp = bridge_port_find(val->var.subs[sub],
372 bif)) == NULL ||
373 (bp = bridge_port_bif_next(bp)) == NULL)
374 return (SNMP_ERR_NOSUCHNAME);
375 }
376 val->var.len = sub + 1;
377 val->var.subs[sub] = bp->port_no;
378 break;
379
380 case SNMP_OP_SET:
381 return (SNMP_ERR_NOT_WRITEABLE);
382
383 case SNMP_OP_ROLLBACK:
384 case SNMP_OP_COMMIT:
356 switch (op) {
357 case SNMP_OP_GET:
358 if (val->var.len - sub != 1)
359 return (SNMP_ERR_NOSUCHNAME);
360 if ((bp = bridge_port_find(val->var.subs[sub],
361 bif)) == NULL)
362 return (SNMP_ERR_NOSUCHNAME);
363 break;
364
365 case SNMP_OP_GETNEXT:
366 if (val->var.len - sub == 0) {
367 if ((bp = bridge_port_bif_first(bif)) == NULL)
368 return (SNMP_ERR_NOSUCHNAME);
369 } else {
370 if ((bp = bridge_port_find(val->var.subs[sub],
371 bif)) == NULL ||
372 (bp = bridge_port_bif_next(bp)) == NULL)
373 return (SNMP_ERR_NOSUCHNAME);
374 }
375 val->var.len = sub + 1;
376 val->var.subs[sub] = bp->port_no;
377 break;
378
379 case SNMP_OP_SET:
380 return (SNMP_ERR_NOT_WRITEABLE);
381
382 case SNMP_OP_ROLLBACK:
383 case SNMP_OP_COMMIT:
384 default:
385 abort();
386 }
387
388 switch (val->var.subs[sub - 1]) {
389 case LEAF_dot1dBasePort:
390 val->v.integer = bp->port_no;
391 break;
392 case LEAF_dot1dBasePortIfIndex:
393 val->v.integer = bp->if_idx;
394 break;
395 case LEAF_dot1dBasePortCircuit:
396 val->v.oid = bp->circuit;
397 break;
398 case LEAF_dot1dBasePortDelayExceededDiscards:
399 val->v.uint32 = bp->dly_ex_drops;
400 break;
401 case LEAF_dot1dBasePortMtuExceededDiscards:
402 val->v.uint32 = bp->dly_mtu_drops;
403 break;
404 }
405
406 return (SNMP_ERR_NOERROR);
407}
408
409int
410op_dot1d_stp_port(struct snmp_context *ctx, struct snmp_value *val,
411 uint sub, uint iidx __unused, enum snmp_op op)
412{
413 int ret;
414 struct bridge_if *bif;
415 struct bridge_port *bp;
416
417 if ((bif = bridge_get_default()) == NULL)
418 return (SNMP_ERR_NOSUCHNAME);
419
420 if (time(NULL) - bif->ports_age > bridge_get_data_maxage() &&
421 bridge_update_memif(bif) <= 0)
422 return (SNMP_ERR_NOSUCHNAME);
423
385 abort();
386 }
387
388 switch (val->var.subs[sub - 1]) {
389 case LEAF_dot1dBasePort:
390 val->v.integer = bp->port_no;
391 break;
392 case LEAF_dot1dBasePortIfIndex:
393 val->v.integer = bp->if_idx;
394 break;
395 case LEAF_dot1dBasePortCircuit:
396 val->v.oid = bp->circuit;
397 break;
398 case LEAF_dot1dBasePortDelayExceededDiscards:
399 val->v.uint32 = bp->dly_ex_drops;
400 break;
401 case LEAF_dot1dBasePortMtuExceededDiscards:
402 val->v.uint32 = bp->dly_mtu_drops;
403 break;
404 }
405
406 return (SNMP_ERR_NOERROR);
407}
408
409int
410op_dot1d_stp_port(struct snmp_context *ctx, struct snmp_value *val,
411 uint sub, uint iidx __unused, enum snmp_op op)
412{
413 int ret;
414 struct bridge_if *bif;
415 struct bridge_port *bp;
416
417 if ((bif = bridge_get_default()) == NULL)
418 return (SNMP_ERR_NOSUCHNAME);
419
420 if (time(NULL) - bif->ports_age > bridge_get_data_maxage() &&
421 bridge_update_memif(bif) <= 0)
422 return (SNMP_ERR_NOSUCHNAME);
423
424 bp = NULL; /* Make the compiler happy. */
425
426 switch (op) {
427 case SNMP_OP_GET:
428 if (val->var.len - sub != 1)
429 return (SNMP_ERR_NOSUCHNAME);
430 if ((bp = bridge_port_find(val->var.subs[sub],
431 bif)) == NULL)
432 return (SNMP_ERR_NOSUCHNAME);
433 break;
434
435 case SNMP_OP_GETNEXT:
436 if (val->var.len - sub == 0) {
437 if ((bp = bridge_port_bif_first(bif)) == NULL)
438 return (SNMP_ERR_NOSUCHNAME);
439 } else {
440 if ((bp = bridge_port_find(val->var.subs[sub],
441 bif)) == NULL ||
442 (bp = bridge_port_bif_next(bp)) == NULL)
443 return (SNMP_ERR_NOSUCHNAME);
444 }
445 val->var.len = sub + 1;
446 val->var.subs[sub] = bp->port_no;
447 break;
448
449 case SNMP_OP_SET:
450 if (val->var.len - sub != 1)
451 return (SNMP_ERR_NOSUCHNAME);
452 if ((bp = bridge_port_find(val->var.subs[sub],
453 bif)) == NULL)
454 return (SNMP_ERR_NOSUCHNAME);
455
456 switch (val->var.subs[sub - 1]) {
457 case LEAF_dot1dStpPortPriority:
458 ctx->scratch->int1 = bp->priority;
459 ret = bridge_port_set_priority(bif->bif_name, bp,
460 val->v.integer);
461 break;
462 case LEAF_dot1dStpPortEnable:
463 ctx->scratch->int1 = bp->enable;
464 ret = bridge_port_set_stp_enable(bif->bif_name,
465 bp, val->v.integer);
466 break;
467 case LEAF_dot1dStpPortPathCost:
468 ctx->scratch->int1 = bp->path_cost;
469 ret = bridge_port_set_path_cost(bif->bif_name, bp,
470 val->v.integer);
471 break;
472 case LEAF_dot1dStpPort:
473 case LEAF_dot1dStpPortState:
474 case LEAF_dot1dStpPortDesignatedRoot:
475 case LEAF_dot1dStpPortDesignatedCost:
476 case LEAF_dot1dStpPortDesignatedBridge:
477 case LEAF_dot1dStpPortDesignatedPort:
478 case LEAF_dot1dStpPortForwardTransitions:
479 return (SNMP_ERR_NOT_WRITEABLE);
480 default:
481 return (SNMP_ERR_NOSUCHNAME);
482 }
483 if (ret == 0)
484 return (SNMP_ERR_NOERROR);
485 else if (ret == -2)
486 return (SNMP_ERR_WRONG_VALUE);
487 return (SNMP_ERR_GENERR);
488
489 case SNMP_OP_ROLLBACK:
490 if ((bp = bridge_port_find(val->var.subs[sub],
491 bif)) == NULL)
492 return (SNMP_ERR_GENERR);
493 switch (val->var.subs[sub - 1]) {
494 case LEAF_dot1dStpPortPriority:
495 bridge_port_set_priority(bif->bif_name, bp,
496 ctx->scratch->int1);
497 break;
498 case LEAF_dot1dStpPortEnable:
499 bridge_port_set_stp_enable(bif->bif_name, bp,
500 ctx->scratch->int1);
501 break;
502 case LEAF_dot1dStpPortPathCost:
503 bridge_port_set_path_cost(bif->bif_name, bp,
504 ctx->scratch->int1);
505 break;
506 }
507 return (SNMP_ERR_NOERROR);
508
509 case SNMP_OP_COMMIT:
510 return (SNMP_ERR_NOERROR);
424 switch (op) {
425 case SNMP_OP_GET:
426 if (val->var.len - sub != 1)
427 return (SNMP_ERR_NOSUCHNAME);
428 if ((bp = bridge_port_find(val->var.subs[sub],
429 bif)) == NULL)
430 return (SNMP_ERR_NOSUCHNAME);
431 break;
432
433 case SNMP_OP_GETNEXT:
434 if (val->var.len - sub == 0) {
435 if ((bp = bridge_port_bif_first(bif)) == NULL)
436 return (SNMP_ERR_NOSUCHNAME);
437 } else {
438 if ((bp = bridge_port_find(val->var.subs[sub],
439 bif)) == NULL ||
440 (bp = bridge_port_bif_next(bp)) == NULL)
441 return (SNMP_ERR_NOSUCHNAME);
442 }
443 val->var.len = sub + 1;
444 val->var.subs[sub] = bp->port_no;
445 break;
446
447 case SNMP_OP_SET:
448 if (val->var.len - sub != 1)
449 return (SNMP_ERR_NOSUCHNAME);
450 if ((bp = bridge_port_find(val->var.subs[sub],
451 bif)) == NULL)
452 return (SNMP_ERR_NOSUCHNAME);
453
454 switch (val->var.subs[sub - 1]) {
455 case LEAF_dot1dStpPortPriority:
456 ctx->scratch->int1 = bp->priority;
457 ret = bridge_port_set_priority(bif->bif_name, bp,
458 val->v.integer);
459 break;
460 case LEAF_dot1dStpPortEnable:
461 ctx->scratch->int1 = bp->enable;
462 ret = bridge_port_set_stp_enable(bif->bif_name,
463 bp, val->v.integer);
464 break;
465 case LEAF_dot1dStpPortPathCost:
466 ctx->scratch->int1 = bp->path_cost;
467 ret = bridge_port_set_path_cost(bif->bif_name, bp,
468 val->v.integer);
469 break;
470 case LEAF_dot1dStpPort:
471 case LEAF_dot1dStpPortState:
472 case LEAF_dot1dStpPortDesignatedRoot:
473 case LEAF_dot1dStpPortDesignatedCost:
474 case LEAF_dot1dStpPortDesignatedBridge:
475 case LEAF_dot1dStpPortDesignatedPort:
476 case LEAF_dot1dStpPortForwardTransitions:
477 return (SNMP_ERR_NOT_WRITEABLE);
478 default:
479 return (SNMP_ERR_NOSUCHNAME);
480 }
481 if (ret == 0)
482 return (SNMP_ERR_NOERROR);
483 else if (ret == -2)
484 return (SNMP_ERR_WRONG_VALUE);
485 return (SNMP_ERR_GENERR);
486
487 case SNMP_OP_ROLLBACK:
488 if ((bp = bridge_port_find(val->var.subs[sub],
489 bif)) == NULL)
490 return (SNMP_ERR_GENERR);
491 switch (val->var.subs[sub - 1]) {
492 case LEAF_dot1dStpPortPriority:
493 bridge_port_set_priority(bif->bif_name, bp,
494 ctx->scratch->int1);
495 break;
496 case LEAF_dot1dStpPortEnable:
497 bridge_port_set_stp_enable(bif->bif_name, bp,
498 ctx->scratch->int1);
499 break;
500 case LEAF_dot1dStpPortPathCost:
501 bridge_port_set_path_cost(bif->bif_name, bp,
502 ctx->scratch->int1);
503 break;
504 }
505 return (SNMP_ERR_NOERROR);
506
507 case SNMP_OP_COMMIT:
508 return (SNMP_ERR_NOERROR);
509
510 default:
511 abort();
511 }
512
513 ret = SNMP_ERR_NOERROR;
514 switch (val->var.subs[sub - 1]) {
515 case LEAF_dot1dStpPort:
516 val->v.integer = bp->port_no;
517 break;
518 case LEAF_dot1dStpPortPriority:
519 val->v.integer = bp->priority;
520 break;
521 case LEAF_dot1dStpPortState:
522 val->v.integer = bp->state;
523 break;
524 case LEAF_dot1dStpPortEnable:
525 val->v.integer = bp->enable;
526 break;
527 case LEAF_dot1dStpPortPathCost:
528 val->v.integer = bp->path_cost;
529 break;
530 case LEAF_dot1dStpPortDesignatedRoot:
531 ret = string_get(val, bp->design_root,
532 SNMP_BRIDGE_ID_LEN);
533 break;
534 case LEAF_dot1dStpPortDesignatedCost:
535 val->v.integer = bp->design_cost;
536 break;
537 case LEAF_dot1dStpPortDesignatedBridge:
538 ret = string_get(val, bp->design_bridge,
539 SNMP_BRIDGE_ID_LEN);
540 break;
541 case LEAF_dot1dStpPortDesignatedPort:
542 ret = string_get(val, bp->design_port, 2);
543 break;
544 case LEAF_dot1dStpPortForwardTransitions:
545 val->v.uint32 = bp->fwd_trans;
546 break;
547 }
548
549 return (ret);
550}
551
552int
553op_dot1d_stp_ext_port(struct snmp_context *ctx, struct snmp_value *val,
554 uint sub, uint iidx __unused, enum snmp_op op)
555{
556 int ret;
557 struct bridge_if *bif;
558 struct bridge_port *bp;
559
560 if ((bif = bridge_get_default()) == NULL)
561 return (SNMP_ERR_NOSUCHNAME);
562
563 if (time(NULL) - bif->ports_age > bridge_get_data_maxage() &&
564 bridge_update_memif(bif) <= 0)
565 return (SNMP_ERR_NOSUCHNAME);
566
512 }
513
514 ret = SNMP_ERR_NOERROR;
515 switch (val->var.subs[sub - 1]) {
516 case LEAF_dot1dStpPort:
517 val->v.integer = bp->port_no;
518 break;
519 case LEAF_dot1dStpPortPriority:
520 val->v.integer = bp->priority;
521 break;
522 case LEAF_dot1dStpPortState:
523 val->v.integer = bp->state;
524 break;
525 case LEAF_dot1dStpPortEnable:
526 val->v.integer = bp->enable;
527 break;
528 case LEAF_dot1dStpPortPathCost:
529 val->v.integer = bp->path_cost;
530 break;
531 case LEAF_dot1dStpPortDesignatedRoot:
532 ret = string_get(val, bp->design_root,
533 SNMP_BRIDGE_ID_LEN);
534 break;
535 case LEAF_dot1dStpPortDesignatedCost:
536 val->v.integer = bp->design_cost;
537 break;
538 case LEAF_dot1dStpPortDesignatedBridge:
539 ret = string_get(val, bp->design_bridge,
540 SNMP_BRIDGE_ID_LEN);
541 break;
542 case LEAF_dot1dStpPortDesignatedPort:
543 ret = string_get(val, bp->design_port, 2);
544 break;
545 case LEAF_dot1dStpPortForwardTransitions:
546 val->v.uint32 = bp->fwd_trans;
547 break;
548 }
549
550 return (ret);
551}
552
553int
554op_dot1d_stp_ext_port(struct snmp_context *ctx, struct snmp_value *val,
555 uint sub, uint iidx __unused, enum snmp_op op)
556{
557 int ret;
558 struct bridge_if *bif;
559 struct bridge_port *bp;
560
561 if ((bif = bridge_get_default()) == NULL)
562 return (SNMP_ERR_NOSUCHNAME);
563
564 if (time(NULL) - bif->ports_age > bridge_get_data_maxage() &&
565 bridge_update_memif(bif) <= 0)
566 return (SNMP_ERR_NOSUCHNAME);
567
567 bp = NULL; /* Make the compiler happy. */
568 switch (op) {
569 case SNMP_OP_GET:
570 if (val->var.len - sub != 1)
571 return (SNMP_ERR_NOSUCHNAME);
572 if ((bp = bridge_port_find(val->var.subs[sub],
573 bif)) == NULL)
574 return (SNMP_ERR_NOSUCHNAME);
575 break;
576
577 case SNMP_OP_GETNEXT:
578 if (val->var.len - sub == 0) {
579 if ((bp = bridge_port_bif_first(bif)) == NULL)
580 return (SNMP_ERR_NOSUCHNAME);
581 } else {
582 if ((bp = bridge_port_find(val->var.subs[sub],
583 bif)) == NULL ||
584 (bp = bridge_port_bif_next(bp)) == NULL)
585 return (SNMP_ERR_NOSUCHNAME);
586 }
587 val->var.len = sub + 1;
588 val->var.subs[sub] = bp->port_no;
589 break;
590
591 case SNMP_OP_SET:
592 if (val->var.len - sub != 1)
593 return (SNMP_ERR_NOSUCHNAME);
594 if ((bp = bridge_port_find(val->var.subs[sub],
595 bif)) == NULL)
596 return (SNMP_ERR_NOSUCHNAME);
597
598 switch (val->var.subs[sub - 1]) {
599 case LEAF_dot1dStpPortAdminEdgePort:
600 ctx->scratch->int1 = bp->admin_edge;
601 ret = bridge_port_set_admin_edge(bif->bif_name, bp,
602 val->v.integer);
603 break;
604 case LEAF_dot1dStpPortAdminPointToPoint:
605 ctx->scratch->int1 = bp->admin_p2p;
606 ret = bridge_port_set_admin_p2p(bif->bif_name, bp,
607 val->v.integer);
608 break;
609 case LEAF_dot1dStpPortAdminPathCost:
610 ctx->scratch->int1 = bp->admin_path_cost;
611 ret = bridge_port_set_path_cost(bif->bif_name, bp,
612 val->v.integer);
613 break;
614 case LEAF_dot1dStpPortProtocolMigration:
615 case LEAF_dot1dStpPortOperEdgePort:
616 case LEAF_dot1dStpPortOperPointToPoint:
617 return (SNMP_ERR_NOT_WRITEABLE);
618 default:
619 return (SNMP_ERR_NOSUCHNAME);
620 }
621
622 if (ret == 0)
623 return (SNMP_ERR_NOERROR);
624 else if (ret == -2)
625 return (SNMP_ERR_WRONG_VALUE);
626 return (SNMP_ERR_GENERR);
627
628 case SNMP_OP_ROLLBACK:
629 if ((bp = bridge_port_find(val->var.subs[sub],
630 bif)) == NULL)
631 return (SNMP_ERR_GENERR);
632
633 switch (val->var.subs[sub - 1]) {
634 case LEAF_dot1dStpPortAdminEdgePort:
635 bridge_port_set_admin_edge(bif->bif_name, bp,
636 ctx->scratch->int1);
637 break;
638 case LEAF_dot1dStpPortAdminPointToPoint:
639 bridge_port_set_admin_p2p(bif->bif_name, bp,
640 ctx->scratch->int1);
641 break;
642 case LEAF_dot1dStpPortAdminPathCost:
643 bridge_port_set_path_cost(bif->bif_name, bp,
644 ctx->scratch->int1);
645 break;
646 }
647 return (SNMP_ERR_NOERROR);
648
649 case SNMP_OP_COMMIT:
650 return (SNMP_ERR_NOERROR);
568 switch (op) {
569 case SNMP_OP_GET:
570 if (val->var.len - sub != 1)
571 return (SNMP_ERR_NOSUCHNAME);
572 if ((bp = bridge_port_find(val->var.subs[sub],
573 bif)) == NULL)
574 return (SNMP_ERR_NOSUCHNAME);
575 break;
576
577 case SNMP_OP_GETNEXT:
578 if (val->var.len - sub == 0) {
579 if ((bp = bridge_port_bif_first(bif)) == NULL)
580 return (SNMP_ERR_NOSUCHNAME);
581 } else {
582 if ((bp = bridge_port_find(val->var.subs[sub],
583 bif)) == NULL ||
584 (bp = bridge_port_bif_next(bp)) == NULL)
585 return (SNMP_ERR_NOSUCHNAME);
586 }
587 val->var.len = sub + 1;
588 val->var.subs[sub] = bp->port_no;
589 break;
590
591 case SNMP_OP_SET:
592 if (val->var.len - sub != 1)
593 return (SNMP_ERR_NOSUCHNAME);
594 if ((bp = bridge_port_find(val->var.subs[sub],
595 bif)) == NULL)
596 return (SNMP_ERR_NOSUCHNAME);
597
598 switch (val->var.subs[sub - 1]) {
599 case LEAF_dot1dStpPortAdminEdgePort:
600 ctx->scratch->int1 = bp->admin_edge;
601 ret = bridge_port_set_admin_edge(bif->bif_name, bp,
602 val->v.integer);
603 break;
604 case LEAF_dot1dStpPortAdminPointToPoint:
605 ctx->scratch->int1 = bp->admin_p2p;
606 ret = bridge_port_set_admin_p2p(bif->bif_name, bp,
607 val->v.integer);
608 break;
609 case LEAF_dot1dStpPortAdminPathCost:
610 ctx->scratch->int1 = bp->admin_path_cost;
611 ret = bridge_port_set_path_cost(bif->bif_name, bp,
612 val->v.integer);
613 break;
614 case LEAF_dot1dStpPortProtocolMigration:
615 case LEAF_dot1dStpPortOperEdgePort:
616 case LEAF_dot1dStpPortOperPointToPoint:
617 return (SNMP_ERR_NOT_WRITEABLE);
618 default:
619 return (SNMP_ERR_NOSUCHNAME);
620 }
621
622 if (ret == 0)
623 return (SNMP_ERR_NOERROR);
624 else if (ret == -2)
625 return (SNMP_ERR_WRONG_VALUE);
626 return (SNMP_ERR_GENERR);
627
628 case SNMP_OP_ROLLBACK:
629 if ((bp = bridge_port_find(val->var.subs[sub],
630 bif)) == NULL)
631 return (SNMP_ERR_GENERR);
632
633 switch (val->var.subs[sub - 1]) {
634 case LEAF_dot1dStpPortAdminEdgePort:
635 bridge_port_set_admin_edge(bif->bif_name, bp,
636 ctx->scratch->int1);
637 break;
638 case LEAF_dot1dStpPortAdminPointToPoint:
639 bridge_port_set_admin_p2p(bif->bif_name, bp,
640 ctx->scratch->int1);
641 break;
642 case LEAF_dot1dStpPortAdminPathCost:
643 bridge_port_set_path_cost(bif->bif_name, bp,
644 ctx->scratch->int1);
645 break;
646 }
647 return (SNMP_ERR_NOERROR);
648
649 case SNMP_OP_COMMIT:
650 return (SNMP_ERR_NOERROR);
651
652 default:
653 abort();
651 }
652
653 switch (val->var.subs[sub - 1]) {
654 case LEAF_dot1dStpPortProtocolMigration:
655 val->v.integer = bp->proto_migr;
656 break;
657 case LEAF_dot1dStpPortAdminEdgePort:
658 val->v.integer = bp->admin_edge;
659 break;
660 case LEAF_dot1dStpPortOperEdgePort:
661 val->v.integer = bp->oper_edge;
662 break;
663 case LEAF_dot1dStpPortAdminPointToPoint:
664 val->v.integer = bp->admin_p2p;
665 break;
666 case LEAF_dot1dStpPortOperPointToPoint:
667 val->v.integer = bp->oper_p2p;
668 break;
669 case LEAF_dot1dStpPortAdminPathCost:
670 val->v.integer = bp->admin_path_cost;
671 break;
672 }
673
674 return (SNMP_ERR_NOERROR);
675}
676
677int
678op_dot1d_tp_port(struct snmp_context *c __unused, struct snmp_value *val,
679 uint sub, uint iidx __unused, enum snmp_op op)
680{
681 struct bridge_if *bif;
682 struct bridge_port *bp;
683
684 if ((bif = bridge_get_default()) == NULL)
685 return (SNMP_ERR_NOSUCHNAME);
686
687 if (time(NULL) - bif->ports_age > bridge_get_data_maxage() &&
688 bridge_update_memif(bif) <= 0)
689 return (SNMP_ERR_NOSUCHNAME);
690
654 }
655
656 switch (val->var.subs[sub - 1]) {
657 case LEAF_dot1dStpPortProtocolMigration:
658 val->v.integer = bp->proto_migr;
659 break;
660 case LEAF_dot1dStpPortAdminEdgePort:
661 val->v.integer = bp->admin_edge;
662 break;
663 case LEAF_dot1dStpPortOperEdgePort:
664 val->v.integer = bp->oper_edge;
665 break;
666 case LEAF_dot1dStpPortAdminPointToPoint:
667 val->v.integer = bp->admin_p2p;
668 break;
669 case LEAF_dot1dStpPortOperPointToPoint:
670 val->v.integer = bp->oper_p2p;
671 break;
672 case LEAF_dot1dStpPortAdminPathCost:
673 val->v.integer = bp->admin_path_cost;
674 break;
675 }
676
677 return (SNMP_ERR_NOERROR);
678}
679
680int
681op_dot1d_tp_port(struct snmp_context *c __unused, struct snmp_value *val,
682 uint sub, uint iidx __unused, enum snmp_op op)
683{
684 struct bridge_if *bif;
685 struct bridge_port *bp;
686
687 if ((bif = bridge_get_default()) == NULL)
688 return (SNMP_ERR_NOSUCHNAME);
689
690 if (time(NULL) - bif->ports_age > bridge_get_data_maxage() &&
691 bridge_update_memif(bif) <= 0)
692 return (SNMP_ERR_NOSUCHNAME);
693
691 bp = NULL; /* Make the compiler happy. */
692 switch (op) {
693 case SNMP_OP_GET:
694 if (val->var.len - sub != 1)
695 return (SNMP_ERR_NOSUCHNAME);
696 if ((bp = bridge_port_find(val->var.subs[sub],
697 bif)) == NULL)
698 return (SNMP_ERR_NOSUCHNAME);
699 break;
700
701 case SNMP_OP_GETNEXT:
702 if (val->var.len - sub == 0) {
703 if ((bp = bridge_port_bif_first(bif)) == NULL)
704 return (SNMP_ERR_NOSUCHNAME);
705 } else {
706 if ((bp = bridge_port_find(val->var.subs[sub],
707 bif)) == NULL ||
708 (bp = bridge_port_bif_next(bp)) == NULL)
709 return (SNMP_ERR_NOSUCHNAME);
710 }
711 val->var.len = sub + 1;
712 val->var.subs[sub] = bp->port_no;
713 break;
714
715 case SNMP_OP_SET:
716 return (SNMP_ERR_NOT_WRITEABLE);
717
718 case SNMP_OP_ROLLBACK:
719 case SNMP_OP_COMMIT:
694 switch (op) {
695 case SNMP_OP_GET:
696 if (val->var.len - sub != 1)
697 return (SNMP_ERR_NOSUCHNAME);
698 if ((bp = bridge_port_find(val->var.subs[sub],
699 bif)) == NULL)
700 return (SNMP_ERR_NOSUCHNAME);
701 break;
702
703 case SNMP_OP_GETNEXT:
704 if (val->var.len - sub == 0) {
705 if ((bp = bridge_port_bif_first(bif)) == NULL)
706 return (SNMP_ERR_NOSUCHNAME);
707 } else {
708 if ((bp = bridge_port_find(val->var.subs[sub],
709 bif)) == NULL ||
710 (bp = bridge_port_bif_next(bp)) == NULL)
711 return (SNMP_ERR_NOSUCHNAME);
712 }
713 val->var.len = sub + 1;
714 val->var.subs[sub] = bp->port_no;
715 break;
716
717 case SNMP_OP_SET:
718 return (SNMP_ERR_NOT_WRITEABLE);
719
720 case SNMP_OP_ROLLBACK:
721 case SNMP_OP_COMMIT:
722 default:
720 abort();
721 }
722
723 switch (val->var.subs[sub - 1]) {
724 case LEAF_dot1dTpPort:
725 val->v.integer = bp->port_no;
726 break;
727 case LEAF_dot1dTpPortMaxInfo:
728 val->v.integer = bp->max_info;
729 break;
730 case LEAF_dot1dTpPortInFrames:
731 val->v.uint32 = bp->in_frames;
732 break;
733 case LEAF_dot1dTpPortOutFrames:
734 val->v.uint32 = bp->out_frames;
735 break;
736 case LEAF_dot1dTpPortInDiscards:
737 val->v.uint32 = bp->in_drops;
738 break;
739 }
740
741 return (SNMP_ERR_NOERROR);
742}
743
744/*
745 * Private BEGEMOT-BRIDGE-MIB specifics.
746 */
747
748/*
749 * Construct a bridge port entry index.
750 */
751static int
752bridge_port_index_append(struct asn_oid *oid, uint sub,
753 const struct bridge_port *bp)
754{
755 uint i;
756 const char *b_name;
757
758 if ((b_name = bridge_if_find_name(bp->sysindex)) == NULL)
759 return (-1);
760
761 oid->len = sub + strlen(b_name) + 1 + 1;
762 oid->subs[sub] = strlen(b_name);
763
764 for (i = 1; i <= strlen(b_name); i++)
765 oid->subs[sub + i] = b_name[i - 1];
766
767 oid->subs[sub + i] = bp->port_no;
768
769 return (0);
770}
771
772/*
773 * Get the port entry from an entry's index.
774 */
775static struct bridge_port *
776bridge_port_index_get(const struct asn_oid *oid, uint sub, int8_t status)
777{
778 uint i;
779 int32_t port_no;
780 char bif_name[IFNAMSIZ];
781 struct bridge_if *bif;
782 struct bridge_port *bp;
783
784 if (oid->len - sub != oid->subs[sub] + 2 ||
785 oid->subs[sub] >= IFNAMSIZ)
786 return (NULL);
787
788 for (i = 0; i < oid->subs[sub]; i++)
789 bif_name[i] = oid->subs[sub + i + 1];
790 bif_name[i] = '\0';
791
792 port_no = oid->subs[sub + i + 1];
793
794 if ((bif = bridge_if_find_ifname(bif_name)) == NULL)
795 return (NULL);
796
797 if ((bp = bridge_port_find(port_no, bif)) == NULL ||
798 (status == 0 && bp->status != RowStatus_active))
799 return (NULL);
800
801 return (bp);
802}
803
804/*
805 * Get the next port entry from an entry's index.
806 */
807static struct bridge_port *
808bridge_port_index_getnext(const struct asn_oid *oid, uint sub, int8_t status)
809{
810 uint i;
811 int32_t port_no;
812 char bif_name[IFNAMSIZ];
813 struct bridge_if *bif;
814 struct bridge_port *bp;
815
816 if (oid->len - sub == 0)
817 bp = bridge_port_first();
818 else {
819 if (oid->len - sub != oid->subs[sub] + 2 ||
820 oid->subs[sub] >= IFNAMSIZ)
821 return (NULL);
822
823 for (i = 0; i < oid->subs[sub]; i++)
824 bif_name[i] = oid->subs[sub + i + 1];
825 bif_name[i] = '\0';
826
827 port_no = oid->subs[sub + i + 1];
828
829 if ((bif = bridge_if_find_ifname(bif_name)) == NULL ||
830 (bp = bridge_port_find(port_no, bif)) == NULL)
831 return (NULL);
832
833 bp = bridge_port_next(bp);
834 }
835
836 if (status == 1)
837 return (bp);
838
839 while (bp != NULL) {
840 if (bp->status == RowStatus_active)
841 break;
842 bp = bridge_port_next(bp);
843 }
844
845 return (bp);
846}
847
848/*
849 * Read the bridge name and port index from a ASN OID structure.
850 */
851static int
852bridge_port_index_decode(const struct asn_oid *oid, uint sub,
853 char *b_name, int32_t *idx)
854{
855 uint i;
856
857 if (oid->len - sub != oid->subs[sub] + 2 ||
858 oid->subs[sub] >= IFNAMSIZ)
859 return (-1);
860
861 for (i = 0; i < oid->subs[sub]; i++)
862 b_name[i] = oid->subs[sub + i + 1];
863 b_name[i] = '\0';
864
865 *idx = oid->subs[sub + i + 1];
866 return (0);
867}
868
869static int
870bridge_port_set_status(struct snmp_context *ctx,
871 struct snmp_value *val, uint sub)
872{
873 int32_t if_idx;
874 char b_name[IFNAMSIZ];
875 struct bridge_if *bif;
876 struct bridge_port *bp;
877 struct mibif *mif;
878
879 if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0)
880 return (SNMP_ERR_INCONS_VALUE);
881
882 if ((bif = bridge_if_find_ifname(b_name)) == NULL ||
883 (mif = mib_find_if(if_idx)) == NULL)
884 return (SNMP_ERR_INCONS_VALUE);
885
886 bp = bridge_port_find(if_idx, bif);
887
888 switch (val->v.integer) {
889 case RowStatus_active:
890 if (bp == NULL)
891 return (SNMP_ERR_INCONS_VALUE);
892
893 if (bp->span_enable == 0)
894 return (SNMP_ERR_INCONS_VALUE);
895
896 ctx->scratch->int1 = bp->status;
897 bp->status = RowStatus_active;
898 break;
899
900 case RowStatus_notInService:
901 if (bp == NULL || bp->span_enable == 0 ||
902 bp->status == RowStatus_active)
903 return (SNMP_ERR_INCONS_VALUE);
904
905 ctx->scratch->int1 = bp->status;
906 bp->status = RowStatus_notInService;
907
908 case RowStatus_notReady:
909 /* FALLTHROUGH */
910 case RowStatus_createAndGo:
911 return (SNMP_ERR_INCONS_VALUE);
912
913 case RowStatus_createAndWait:
914 if (bp != NULL)
915 return (SNMP_ERR_INCONS_VALUE);
916
917 if ((bp = bridge_new_port(mif, bif)) == NULL)
918 return (SNMP_ERR_GENERR);
919
920 ctx->scratch->int1 = RowStatus_destroy;
921 bp->status = RowStatus_notReady;
922 break;
923
924 case RowStatus_destroy:
925 if (bp == NULL)
926 return (SNMP_ERR_INCONS_VALUE);
927
928 ctx->scratch->int1 = bp->status;
929 bp->status = RowStatus_destroy;
930 break;
931 }
932
933 return (SNMP_ERR_NOERROR);
934}
935
936static int
937bridge_port_rollback_status(struct snmp_context *ctx,
938 struct snmp_value *val, uint sub)
939{
940 int32_t if_idx;
941 char b_name[IFNAMSIZ];
942 struct bridge_if *bif;
943 struct bridge_port *bp;
944
945 if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0)
946 return (SNMP_ERR_GENERR);
947
948 if ((bif = bridge_if_find_ifname(b_name)) == NULL ||
949 (bp = bridge_port_find(if_idx, bif)) == NULL)
950 return (SNMP_ERR_GENERR);
951
952 if (ctx->scratch->int1 == RowStatus_destroy)
953 bridge_port_remove(bp, bif);
954 else
955 bp->status = ctx->scratch->int1;
956
957 return (SNMP_ERR_NOERROR);
958}
959
960static int
961bridge_port_commit_status(struct snmp_value *val, uint sub)
962{
963 int32_t if_idx;
964 char b_name[IFNAMSIZ];
965 struct bridge_if *bif;
966 struct bridge_port *bp;
967
968 if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0)
969 return (SNMP_ERR_GENERR);
970
971 if ((bif = bridge_if_find_ifname(b_name)) == NULL ||
972 (bp = bridge_port_find(if_idx, bif)) == NULL)
973 return (SNMP_ERR_GENERR);
974
975 switch (bp->status) {
976 case RowStatus_active:
977 if (bridge_port_addm(bp, b_name) < 0)
978 return (SNMP_ERR_COMMIT_FAILED);
979 break;
980
981 case RowStatus_destroy:
982 if (bridge_port_delm(bp, b_name) < 0)
983 return (SNMP_ERR_COMMIT_FAILED);
984 bridge_port_remove(bp, bif);
985 break;
986 }
987
988 return (SNMP_ERR_NOERROR);
989}
990
991static int
992bridge_port_set_span_enable(struct snmp_context *ctx,
993 struct snmp_value *val, uint sub)
994{
995 int32_t if_idx;
996 char b_name[IFNAMSIZ];
997 struct bridge_if *bif;
998 struct bridge_port *bp;
999 struct mibif *mif;
1000
1001 if (val->v.integer != begemotBridgeBaseSpanEnabled_enabled &&
1002 val->v.integer != begemotBridgeBaseSpanEnabled_disabled)
1003 return (SNMP_ERR_BADVALUE);
1004
1005 if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0)
1006 return (SNMP_ERR_INCONS_VALUE);
1007
1008 if ((bif = bridge_if_find_ifname(b_name)) == NULL)
1009 return (SNMP_ERR_INCONS_VALUE);
1010
1011 if ((bp = bridge_port_find(if_idx, bif)) == NULL) {
1012 if ((mif = mib_find_if(if_idx)) == NULL)
1013 return (SNMP_ERR_INCONS_VALUE);
1014
1015 if ((bp = bridge_new_port(mif, bif)) == NULL)
1016 return (SNMP_ERR_GENERR);
1017
1018 ctx->scratch->int1 = RowStatus_destroy;
1019 } else if (bp->status == RowStatus_active) {
1020 return (SNMP_ERR_INCONS_VALUE);
1021 } else {
1022 ctx->scratch->int1 = bp->status;
1023 }
1024
1025 bp->span_enable = val->v.integer;
1026 bp->status = RowStatus_notInService;
1027
1028 return (SNMP_ERR_NOERROR);
1029}
1030
1031int
1032op_begemot_base_port(struct snmp_context *ctx, struct snmp_value *val,
1033 uint sub, uint iidx __unused, enum snmp_op op)
1034{
1035 int8_t status, which;
1036 struct bridge_port *bp = NULL;
1037
1038 if (time(NULL) - ports_list_age > bridge_get_data_maxage())
1039 bridge_update_all_ports();
1040
1041 which = val->var.subs[sub - 1];
1042 status = 0;
1043
1044 switch (op) {
1045 case SNMP_OP_GET:
1046 if (which == LEAF_begemotBridgeBaseSpanEnabled ||
1047 which == LEAF_begemotBridgeBasePortStatus)
1048 status = 1;
1049 if ((bp = bridge_port_index_get(&val->var, sub,
1050 status)) == NULL)
1051 return (SNMP_ERR_NOSUCHNAME);
1052 break;
1053
1054 case SNMP_OP_GETNEXT:
1055 if (which == LEAF_begemotBridgeBaseSpanEnabled ||
1056 which == LEAF_begemotBridgeBasePortStatus)
1057 status = 1;
1058 if ((bp = bridge_port_index_getnext(&val->var, sub,
1059 status)) == NULL ||
1060 bridge_port_index_append(&val->var, sub, bp) < 0)
1061 return (SNMP_ERR_NOSUCHNAME);
1062 break;
1063
1064 case SNMP_OP_SET:
1065 switch (which) {
1066 case LEAF_begemotBridgeBaseSpanEnabled:
1067 return (bridge_port_set_span_enable(ctx, val, sub));
1068
1069 case LEAF_begemotBridgeBasePortStatus:
1070 return (bridge_port_set_status(ctx, val, sub));
1071
1072 case LEAF_begemotBridgeBasePort:
1073 case LEAF_begemotBridgeBasePortIfIndex:
1074 case LEAF_begemotBridgeBasePortDelayExceededDiscards:
1075 case LEAF_begemotBridgeBasePortMtuExceededDiscards:
1076 return (SNMP_ERR_NOT_WRITEABLE);
1077 }
1078 abort();
1079
1080 case SNMP_OP_ROLLBACK:
1081 switch (which) {
1082 case LEAF_begemotBridgeBaseSpanEnabled:
1083 /* FALLTHROUGH */
1084 case LEAF_begemotBridgeBasePortStatus:
1085 return (bridge_port_rollback_status(ctx, val, sub));
1086 }
1087 return (SNMP_ERR_NOERROR);
1088
1089 case SNMP_OP_COMMIT:
1090 if (which == LEAF_begemotBridgeBasePortStatus)
1091 return (bridge_port_commit_status(val, sub));
1092
1093 return (SNMP_ERR_NOERROR);
1094 }
1095
1096 switch (which) {
1097 case LEAF_begemotBridgeBasePort:
1098 val->v.integer = bp->port_no;
1099 break;
1100 case LEAF_begemotBridgeBasePortIfIndex:
1101 val->v.integer = bp->if_idx;
1102 break;
1103 case LEAF_begemotBridgeBaseSpanEnabled:
1104 val->v.integer = bp->span_enable;
1105 break;
1106 case LEAF_begemotBridgeBasePortDelayExceededDiscards:
1107 val->v.uint32 = bp->dly_ex_drops;
1108 break;
1109 case LEAF_begemotBridgeBasePortMtuExceededDiscards:
1110 val->v.uint32 = bp->dly_mtu_drops;
1111 break;
1112 case LEAF_begemotBridgeBasePortStatus:
1113 val->v.integer = bp->status;
1114 break;
1115 }
1116
1117 return (SNMP_ERR_NOERROR);
1118}
1119
1120int
1121op_begemot_stp_port(struct snmp_context *ctx, struct snmp_value *val,
1122 uint sub, uint iidx __unused, enum snmp_op op)
1123{
1124 int ret;
723 abort();
724 }
725
726 switch (val->var.subs[sub - 1]) {
727 case LEAF_dot1dTpPort:
728 val->v.integer = bp->port_no;
729 break;
730 case LEAF_dot1dTpPortMaxInfo:
731 val->v.integer = bp->max_info;
732 break;
733 case LEAF_dot1dTpPortInFrames:
734 val->v.uint32 = bp->in_frames;
735 break;
736 case LEAF_dot1dTpPortOutFrames:
737 val->v.uint32 = bp->out_frames;
738 break;
739 case LEAF_dot1dTpPortInDiscards:
740 val->v.uint32 = bp->in_drops;
741 break;
742 }
743
744 return (SNMP_ERR_NOERROR);
745}
746
747/*
748 * Private BEGEMOT-BRIDGE-MIB specifics.
749 */
750
751/*
752 * Construct a bridge port entry index.
753 */
754static int
755bridge_port_index_append(struct asn_oid *oid, uint sub,
756 const struct bridge_port *bp)
757{
758 uint i;
759 const char *b_name;
760
761 if ((b_name = bridge_if_find_name(bp->sysindex)) == NULL)
762 return (-1);
763
764 oid->len = sub + strlen(b_name) + 1 + 1;
765 oid->subs[sub] = strlen(b_name);
766
767 for (i = 1; i <= strlen(b_name); i++)
768 oid->subs[sub + i] = b_name[i - 1];
769
770 oid->subs[sub + i] = bp->port_no;
771
772 return (0);
773}
774
775/*
776 * Get the port entry from an entry's index.
777 */
778static struct bridge_port *
779bridge_port_index_get(const struct asn_oid *oid, uint sub, int8_t status)
780{
781 uint i;
782 int32_t port_no;
783 char bif_name[IFNAMSIZ];
784 struct bridge_if *bif;
785 struct bridge_port *bp;
786
787 if (oid->len - sub != oid->subs[sub] + 2 ||
788 oid->subs[sub] >= IFNAMSIZ)
789 return (NULL);
790
791 for (i = 0; i < oid->subs[sub]; i++)
792 bif_name[i] = oid->subs[sub + i + 1];
793 bif_name[i] = '\0';
794
795 port_no = oid->subs[sub + i + 1];
796
797 if ((bif = bridge_if_find_ifname(bif_name)) == NULL)
798 return (NULL);
799
800 if ((bp = bridge_port_find(port_no, bif)) == NULL ||
801 (status == 0 && bp->status != RowStatus_active))
802 return (NULL);
803
804 return (bp);
805}
806
807/*
808 * Get the next port entry from an entry's index.
809 */
810static struct bridge_port *
811bridge_port_index_getnext(const struct asn_oid *oid, uint sub, int8_t status)
812{
813 uint i;
814 int32_t port_no;
815 char bif_name[IFNAMSIZ];
816 struct bridge_if *bif;
817 struct bridge_port *bp;
818
819 if (oid->len - sub == 0)
820 bp = bridge_port_first();
821 else {
822 if (oid->len - sub != oid->subs[sub] + 2 ||
823 oid->subs[sub] >= IFNAMSIZ)
824 return (NULL);
825
826 for (i = 0; i < oid->subs[sub]; i++)
827 bif_name[i] = oid->subs[sub + i + 1];
828 bif_name[i] = '\0';
829
830 port_no = oid->subs[sub + i + 1];
831
832 if ((bif = bridge_if_find_ifname(bif_name)) == NULL ||
833 (bp = bridge_port_find(port_no, bif)) == NULL)
834 return (NULL);
835
836 bp = bridge_port_next(bp);
837 }
838
839 if (status == 1)
840 return (bp);
841
842 while (bp != NULL) {
843 if (bp->status == RowStatus_active)
844 break;
845 bp = bridge_port_next(bp);
846 }
847
848 return (bp);
849}
850
851/*
852 * Read the bridge name and port index from a ASN OID structure.
853 */
854static int
855bridge_port_index_decode(const struct asn_oid *oid, uint sub,
856 char *b_name, int32_t *idx)
857{
858 uint i;
859
860 if (oid->len - sub != oid->subs[sub] + 2 ||
861 oid->subs[sub] >= IFNAMSIZ)
862 return (-1);
863
864 for (i = 0; i < oid->subs[sub]; i++)
865 b_name[i] = oid->subs[sub + i + 1];
866 b_name[i] = '\0';
867
868 *idx = oid->subs[sub + i + 1];
869 return (0);
870}
871
872static int
873bridge_port_set_status(struct snmp_context *ctx,
874 struct snmp_value *val, uint sub)
875{
876 int32_t if_idx;
877 char b_name[IFNAMSIZ];
878 struct bridge_if *bif;
879 struct bridge_port *bp;
880 struct mibif *mif;
881
882 if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0)
883 return (SNMP_ERR_INCONS_VALUE);
884
885 if ((bif = bridge_if_find_ifname(b_name)) == NULL ||
886 (mif = mib_find_if(if_idx)) == NULL)
887 return (SNMP_ERR_INCONS_VALUE);
888
889 bp = bridge_port_find(if_idx, bif);
890
891 switch (val->v.integer) {
892 case RowStatus_active:
893 if (bp == NULL)
894 return (SNMP_ERR_INCONS_VALUE);
895
896 if (bp->span_enable == 0)
897 return (SNMP_ERR_INCONS_VALUE);
898
899 ctx->scratch->int1 = bp->status;
900 bp->status = RowStatus_active;
901 break;
902
903 case RowStatus_notInService:
904 if (bp == NULL || bp->span_enable == 0 ||
905 bp->status == RowStatus_active)
906 return (SNMP_ERR_INCONS_VALUE);
907
908 ctx->scratch->int1 = bp->status;
909 bp->status = RowStatus_notInService;
910
911 case RowStatus_notReady:
912 /* FALLTHROUGH */
913 case RowStatus_createAndGo:
914 return (SNMP_ERR_INCONS_VALUE);
915
916 case RowStatus_createAndWait:
917 if (bp != NULL)
918 return (SNMP_ERR_INCONS_VALUE);
919
920 if ((bp = bridge_new_port(mif, bif)) == NULL)
921 return (SNMP_ERR_GENERR);
922
923 ctx->scratch->int1 = RowStatus_destroy;
924 bp->status = RowStatus_notReady;
925 break;
926
927 case RowStatus_destroy:
928 if (bp == NULL)
929 return (SNMP_ERR_INCONS_VALUE);
930
931 ctx->scratch->int1 = bp->status;
932 bp->status = RowStatus_destroy;
933 break;
934 }
935
936 return (SNMP_ERR_NOERROR);
937}
938
939static int
940bridge_port_rollback_status(struct snmp_context *ctx,
941 struct snmp_value *val, uint sub)
942{
943 int32_t if_idx;
944 char b_name[IFNAMSIZ];
945 struct bridge_if *bif;
946 struct bridge_port *bp;
947
948 if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0)
949 return (SNMP_ERR_GENERR);
950
951 if ((bif = bridge_if_find_ifname(b_name)) == NULL ||
952 (bp = bridge_port_find(if_idx, bif)) == NULL)
953 return (SNMP_ERR_GENERR);
954
955 if (ctx->scratch->int1 == RowStatus_destroy)
956 bridge_port_remove(bp, bif);
957 else
958 bp->status = ctx->scratch->int1;
959
960 return (SNMP_ERR_NOERROR);
961}
962
963static int
964bridge_port_commit_status(struct snmp_value *val, uint sub)
965{
966 int32_t if_idx;
967 char b_name[IFNAMSIZ];
968 struct bridge_if *bif;
969 struct bridge_port *bp;
970
971 if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0)
972 return (SNMP_ERR_GENERR);
973
974 if ((bif = bridge_if_find_ifname(b_name)) == NULL ||
975 (bp = bridge_port_find(if_idx, bif)) == NULL)
976 return (SNMP_ERR_GENERR);
977
978 switch (bp->status) {
979 case RowStatus_active:
980 if (bridge_port_addm(bp, b_name) < 0)
981 return (SNMP_ERR_COMMIT_FAILED);
982 break;
983
984 case RowStatus_destroy:
985 if (bridge_port_delm(bp, b_name) < 0)
986 return (SNMP_ERR_COMMIT_FAILED);
987 bridge_port_remove(bp, bif);
988 break;
989 }
990
991 return (SNMP_ERR_NOERROR);
992}
993
994static int
995bridge_port_set_span_enable(struct snmp_context *ctx,
996 struct snmp_value *val, uint sub)
997{
998 int32_t if_idx;
999 char b_name[IFNAMSIZ];
1000 struct bridge_if *bif;
1001 struct bridge_port *bp;
1002 struct mibif *mif;
1003
1004 if (val->v.integer != begemotBridgeBaseSpanEnabled_enabled &&
1005 val->v.integer != begemotBridgeBaseSpanEnabled_disabled)
1006 return (SNMP_ERR_BADVALUE);
1007
1008 if (bridge_port_index_decode(&val->var, sub, b_name, &if_idx) < 0)
1009 return (SNMP_ERR_INCONS_VALUE);
1010
1011 if ((bif = bridge_if_find_ifname(b_name)) == NULL)
1012 return (SNMP_ERR_INCONS_VALUE);
1013
1014 if ((bp = bridge_port_find(if_idx, bif)) == NULL) {
1015 if ((mif = mib_find_if(if_idx)) == NULL)
1016 return (SNMP_ERR_INCONS_VALUE);
1017
1018 if ((bp = bridge_new_port(mif, bif)) == NULL)
1019 return (SNMP_ERR_GENERR);
1020
1021 ctx->scratch->int1 = RowStatus_destroy;
1022 } else if (bp->status == RowStatus_active) {
1023 return (SNMP_ERR_INCONS_VALUE);
1024 } else {
1025 ctx->scratch->int1 = bp->status;
1026 }
1027
1028 bp->span_enable = val->v.integer;
1029 bp->status = RowStatus_notInService;
1030
1031 return (SNMP_ERR_NOERROR);
1032}
1033
1034int
1035op_begemot_base_port(struct snmp_context *ctx, struct snmp_value *val,
1036 uint sub, uint iidx __unused, enum snmp_op op)
1037{
1038 int8_t status, which;
1039 struct bridge_port *bp = NULL;
1040
1041 if (time(NULL) - ports_list_age > bridge_get_data_maxage())
1042 bridge_update_all_ports();
1043
1044 which = val->var.subs[sub - 1];
1045 status = 0;
1046
1047 switch (op) {
1048 case SNMP_OP_GET:
1049 if (which == LEAF_begemotBridgeBaseSpanEnabled ||
1050 which == LEAF_begemotBridgeBasePortStatus)
1051 status = 1;
1052 if ((bp = bridge_port_index_get(&val->var, sub,
1053 status)) == NULL)
1054 return (SNMP_ERR_NOSUCHNAME);
1055 break;
1056
1057 case SNMP_OP_GETNEXT:
1058 if (which == LEAF_begemotBridgeBaseSpanEnabled ||
1059 which == LEAF_begemotBridgeBasePortStatus)
1060 status = 1;
1061 if ((bp = bridge_port_index_getnext(&val->var, sub,
1062 status)) == NULL ||
1063 bridge_port_index_append(&val->var, sub, bp) < 0)
1064 return (SNMP_ERR_NOSUCHNAME);
1065 break;
1066
1067 case SNMP_OP_SET:
1068 switch (which) {
1069 case LEAF_begemotBridgeBaseSpanEnabled:
1070 return (bridge_port_set_span_enable(ctx, val, sub));
1071
1072 case LEAF_begemotBridgeBasePortStatus:
1073 return (bridge_port_set_status(ctx, val, sub));
1074
1075 case LEAF_begemotBridgeBasePort:
1076 case LEAF_begemotBridgeBasePortIfIndex:
1077 case LEAF_begemotBridgeBasePortDelayExceededDiscards:
1078 case LEAF_begemotBridgeBasePortMtuExceededDiscards:
1079 return (SNMP_ERR_NOT_WRITEABLE);
1080 }
1081 abort();
1082
1083 case SNMP_OP_ROLLBACK:
1084 switch (which) {
1085 case LEAF_begemotBridgeBaseSpanEnabled:
1086 /* FALLTHROUGH */
1087 case LEAF_begemotBridgeBasePortStatus:
1088 return (bridge_port_rollback_status(ctx, val, sub));
1089 }
1090 return (SNMP_ERR_NOERROR);
1091
1092 case SNMP_OP_COMMIT:
1093 if (which == LEAF_begemotBridgeBasePortStatus)
1094 return (bridge_port_commit_status(val, sub));
1095
1096 return (SNMP_ERR_NOERROR);
1097 }
1098
1099 switch (which) {
1100 case LEAF_begemotBridgeBasePort:
1101 val->v.integer = bp->port_no;
1102 break;
1103 case LEAF_begemotBridgeBasePortIfIndex:
1104 val->v.integer = bp->if_idx;
1105 break;
1106 case LEAF_begemotBridgeBaseSpanEnabled:
1107 val->v.integer = bp->span_enable;
1108 break;
1109 case LEAF_begemotBridgeBasePortDelayExceededDiscards:
1110 val->v.uint32 = bp->dly_ex_drops;
1111 break;
1112 case LEAF_begemotBridgeBasePortMtuExceededDiscards:
1113 val->v.uint32 = bp->dly_mtu_drops;
1114 break;
1115 case LEAF_begemotBridgeBasePortStatus:
1116 val->v.integer = bp->status;
1117 break;
1118 }
1119
1120 return (SNMP_ERR_NOERROR);
1121}
1122
1123int
1124op_begemot_stp_port(struct snmp_context *ctx, struct snmp_value *val,
1125 uint sub, uint iidx __unused, enum snmp_op op)
1126{
1127 int ret;
1125 struct bridge_port *bp = NULL;
1128 struct bridge_port *bp;
1126 const char *b_name;
1127
1128 if (time(NULL) - ports_list_age > bridge_get_data_maxage())
1129 bridge_update_all_ports();
1130
1131 switch (op) {
1132 case SNMP_OP_GET:
1133 if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL)
1134 return (SNMP_ERR_NOSUCHNAME);
1135 break;
1136
1137 case SNMP_OP_GETNEXT:
1138 if ((bp = bridge_port_index_getnext(&val->var, sub, 0)) ==
1139 NULL || bridge_port_index_append(&val->var, sub, bp) < 0)
1140 return (SNMP_ERR_NOSUCHNAME);
1141 break;
1142
1143 case SNMP_OP_SET:
1144 if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL)
1145 return (SNMP_ERR_NOSUCHNAME);
1146 if ((b_name = bridge_if_find_name(bp->sysindex)) == NULL)
1147 return (SNMP_ERR_GENERR);
1148
1149 ret = SNMP_ERR_NOERROR;
1150 switch (val->var.subs[sub - 1]) {
1151 case LEAF_begemotBridgeStpPortPriority:
1152 ctx->scratch->int1 = bp->priority;
1153 ret = bridge_port_set_priority(b_name, bp,
1154 val->v.integer);
1155 break;
1156 case LEAF_begemotBridgeStpPortEnable:
1157 ctx->scratch->int1 = bp->enable;
1158 ret = bridge_port_set_stp_enable(b_name, bp,
1159 val->v.integer);
1160 break;
1161 case LEAF_begemotBridgeStpPortPathCost:
1162 ctx->scratch->int1 = bp->path_cost;
1163 ret = bridge_port_set_path_cost(b_name, bp,
1164 val->v.integer);
1165 break;
1166 case LEAF_begemotBridgeStpPort:
1167 case LEAF_begemotBridgeStpPortState:
1168 case LEAF_begemotBridgeStpPortDesignatedRoot:
1169 case LEAF_begemotBridgeStpPortDesignatedCost:
1170 case LEAF_begemotBridgeStpPortDesignatedBridge:
1171 case LEAF_begemotBridgeStpPortDesignatedPort:
1172 case LEAF_begemotBridgeStpPortForwardTransitions:
1173 return (SNMP_ERR_NOT_WRITEABLE);
1174 }
1175 if (ret == 0)
1176 return (SNMP_ERR_NOERROR);
1177 else if (ret == -2)
1178 return (SNMP_ERR_WRONG_VALUE);
1179 return (SNMP_ERR_GENERR);
1180
1181 case SNMP_OP_ROLLBACK:
1182 if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL ||
1183 (b_name = bridge_if_find_name(bp->sysindex)) == NULL)
1184 return (SNMP_ERR_GENERR);
1185
1186 switch (val->var.subs[sub - 1]) {
1187 case LEAF_begemotBridgeStpPortPriority:
1188 bridge_port_set_priority(b_name, bp,
1189 ctx->scratch->int1);
1190 break;
1191 case LEAF_begemotBridgeStpPortEnable:
1192 bridge_port_set_stp_enable(b_name, bp,
1193 ctx->scratch->int1);
1194 break;
1195 case LEAF_begemotBridgeStpPortPathCost:
1196 bridge_port_set_path_cost(b_name, bp,
1197 ctx->scratch->int1);
1198 break;
1199 }
1200 return (SNMP_ERR_NOERROR);
1201
1202 case SNMP_OP_COMMIT:
1203 return (SNMP_ERR_NOERROR);
1129 const char *b_name;
1130
1131 if (time(NULL) - ports_list_age > bridge_get_data_maxage())
1132 bridge_update_all_ports();
1133
1134 switch (op) {
1135 case SNMP_OP_GET:
1136 if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL)
1137 return (SNMP_ERR_NOSUCHNAME);
1138 break;
1139
1140 case SNMP_OP_GETNEXT:
1141 if ((bp = bridge_port_index_getnext(&val->var, sub, 0)) ==
1142 NULL || bridge_port_index_append(&val->var, sub, bp) < 0)
1143 return (SNMP_ERR_NOSUCHNAME);
1144 break;
1145
1146 case SNMP_OP_SET:
1147 if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL)
1148 return (SNMP_ERR_NOSUCHNAME);
1149 if ((b_name = bridge_if_find_name(bp->sysindex)) == NULL)
1150 return (SNMP_ERR_GENERR);
1151
1152 ret = SNMP_ERR_NOERROR;
1153 switch (val->var.subs[sub - 1]) {
1154 case LEAF_begemotBridgeStpPortPriority:
1155 ctx->scratch->int1 = bp->priority;
1156 ret = bridge_port_set_priority(b_name, bp,
1157 val->v.integer);
1158 break;
1159 case LEAF_begemotBridgeStpPortEnable:
1160 ctx->scratch->int1 = bp->enable;
1161 ret = bridge_port_set_stp_enable(b_name, bp,
1162 val->v.integer);
1163 break;
1164 case LEAF_begemotBridgeStpPortPathCost:
1165 ctx->scratch->int1 = bp->path_cost;
1166 ret = bridge_port_set_path_cost(b_name, bp,
1167 val->v.integer);
1168 break;
1169 case LEAF_begemotBridgeStpPort:
1170 case LEAF_begemotBridgeStpPortState:
1171 case LEAF_begemotBridgeStpPortDesignatedRoot:
1172 case LEAF_begemotBridgeStpPortDesignatedCost:
1173 case LEAF_begemotBridgeStpPortDesignatedBridge:
1174 case LEAF_begemotBridgeStpPortDesignatedPort:
1175 case LEAF_begemotBridgeStpPortForwardTransitions:
1176 return (SNMP_ERR_NOT_WRITEABLE);
1177 }
1178 if (ret == 0)
1179 return (SNMP_ERR_NOERROR);
1180 else if (ret == -2)
1181 return (SNMP_ERR_WRONG_VALUE);
1182 return (SNMP_ERR_GENERR);
1183
1184 case SNMP_OP_ROLLBACK:
1185 if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL ||
1186 (b_name = bridge_if_find_name(bp->sysindex)) == NULL)
1187 return (SNMP_ERR_GENERR);
1188
1189 switch (val->var.subs[sub - 1]) {
1190 case LEAF_begemotBridgeStpPortPriority:
1191 bridge_port_set_priority(b_name, bp,
1192 ctx->scratch->int1);
1193 break;
1194 case LEAF_begemotBridgeStpPortEnable:
1195 bridge_port_set_stp_enable(b_name, bp,
1196 ctx->scratch->int1);
1197 break;
1198 case LEAF_begemotBridgeStpPortPathCost:
1199 bridge_port_set_path_cost(b_name, bp,
1200 ctx->scratch->int1);
1201 break;
1202 }
1203 return (SNMP_ERR_NOERROR);
1204
1205 case SNMP_OP_COMMIT:
1206 return (SNMP_ERR_NOERROR);
1207
1208 default:
1209 abort();
1204 }
1205
1206 ret = SNMP_ERR_NOERROR;
1207 switch (val->var.subs[sub - 1]) {
1208 case LEAF_begemotBridgeStpPort:
1209 val->v.integer = bp->port_no;
1210 break;
1211 case LEAF_begemotBridgeStpPortPriority:
1212 val->v.integer = bp->priority;
1213 break;
1214 case LEAF_begemotBridgeStpPortState:
1215 val->v.integer = bp->state;
1216 break;
1217 case LEAF_begemotBridgeStpPortEnable:
1218 val->v.integer = bp->enable;
1219 break;
1220 case LEAF_begemotBridgeStpPortPathCost:
1221 val->v.integer = bp->path_cost;
1222 break;
1223 case LEAF_begemotBridgeStpPortDesignatedRoot:
1224 ret = string_get(val, bp->design_root, SNMP_BRIDGE_ID_LEN);
1225 break;
1226 case LEAF_begemotBridgeStpPortDesignatedCost:
1227 val->v.integer = bp->design_cost;
1228 break;
1229 case LEAF_begemotBridgeStpPortDesignatedBridge:
1230 ret = string_get(val, bp->design_bridge, SNMP_BRIDGE_ID_LEN);
1231 break;
1232 case LEAF_begemotBridgeStpPortDesignatedPort:
1233 ret = string_get(val, bp->design_port, 2);
1234 break;
1235 case LEAF_begemotBridgeStpPortForwardTransitions:
1236 val->v.uint32 = bp->fwd_trans;
1237 break;
1238 }
1239
1240 return (ret);
1241}
1242
1243int
1244op_begemot_stp_ext_port(struct snmp_context *ctx, struct snmp_value *val,
1245 uint sub, uint iidx __unused, enum snmp_op op)
1246{
1247 int ret;
1210 }
1211
1212 ret = SNMP_ERR_NOERROR;
1213 switch (val->var.subs[sub - 1]) {
1214 case LEAF_begemotBridgeStpPort:
1215 val->v.integer = bp->port_no;
1216 break;
1217 case LEAF_begemotBridgeStpPortPriority:
1218 val->v.integer = bp->priority;
1219 break;
1220 case LEAF_begemotBridgeStpPortState:
1221 val->v.integer = bp->state;
1222 break;
1223 case LEAF_begemotBridgeStpPortEnable:
1224 val->v.integer = bp->enable;
1225 break;
1226 case LEAF_begemotBridgeStpPortPathCost:
1227 val->v.integer = bp->path_cost;
1228 break;
1229 case LEAF_begemotBridgeStpPortDesignatedRoot:
1230 ret = string_get(val, bp->design_root, SNMP_BRIDGE_ID_LEN);
1231 break;
1232 case LEAF_begemotBridgeStpPortDesignatedCost:
1233 val->v.integer = bp->design_cost;
1234 break;
1235 case LEAF_begemotBridgeStpPortDesignatedBridge:
1236 ret = string_get(val, bp->design_bridge, SNMP_BRIDGE_ID_LEN);
1237 break;
1238 case LEAF_begemotBridgeStpPortDesignatedPort:
1239 ret = string_get(val, bp->design_port, 2);
1240 break;
1241 case LEAF_begemotBridgeStpPortForwardTransitions:
1242 val->v.uint32 = bp->fwd_trans;
1243 break;
1244 }
1245
1246 return (ret);
1247}
1248
1249int
1250op_begemot_stp_ext_port(struct snmp_context *ctx, struct snmp_value *val,
1251 uint sub, uint iidx __unused, enum snmp_op op)
1252{
1253 int ret;
1248 struct bridge_port *bp = NULL;
1254 struct bridge_port *bp;
1249 const char *b_name;
1250
1251 if (time(NULL) - ports_list_age > bridge_get_data_maxage())
1252 bridge_update_all_ports();
1253
1254 switch (op) {
1255 case SNMP_OP_GET:
1256 if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL)
1257 return (SNMP_ERR_NOSUCHNAME);
1258 break;
1259
1260 case SNMP_OP_GETNEXT:
1261 if ((bp = bridge_port_index_getnext(&val->var, sub, 0)) ==
1262 NULL || bridge_port_index_append(&val->var, sub, bp) < 0)
1263 return (SNMP_ERR_NOSUCHNAME);
1264 break;
1265
1266 case SNMP_OP_SET:
1267 if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL)
1268 return (SNMP_ERR_NOSUCHNAME);
1269 if ((b_name = bridge_if_find_name(bp->sysindex)) == NULL)
1270 return (SNMP_ERR_GENERR);
1271
1272 switch (val->var.subs[sub - 1]) {
1273 case LEAF_begemotBridgeStpPortAdminEdgePort:
1274 ctx->scratch->int1 = bp->admin_edge;
1275 ret = bridge_port_set_admin_edge(b_name, bp,
1276 val->v.integer);
1277 break;
1278 case LEAF_begemotBridgeStpPortAdminPointToPoint:
1279 ctx->scratch->int1 = bp->admin_p2p;
1280 ret = bridge_port_set_admin_p2p(b_name, bp,
1281 val->v.integer);
1282 break;
1283 case LEAF_begemotBridgeStpPortAdminPathCost:
1284 ctx->scratch->int1 = bp->admin_path_cost;
1285 ret = bridge_port_set_path_cost(b_name, bp,
1286 val->v.integer);
1287 break;
1288 case LEAF_begemotBridgeStpPortProtocolMigration:
1289 case LEAF_begemotBridgeStpPortOperEdgePort:
1290 case LEAF_begemotBridgeStpPortOperPointToPoint:
1291 return (SNMP_ERR_NOT_WRITEABLE);
1292 default:
1293 return (SNMP_ERR_NOSUCHNAME);
1294 }
1295
1296 if (ret == 0)
1297 return (SNMP_ERR_NOERROR);
1298 else if (ret == -2)
1299 return (SNMP_ERR_WRONG_VALUE);
1300 return (SNMP_ERR_GENERR);
1301
1302 case SNMP_OP_ROLLBACK:
1303 if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL ||
1304 (b_name = bridge_if_find_name(bp->sysindex)) == NULL)
1305 return (SNMP_ERR_GENERR);
1306
1307 switch (val->var.subs[sub - 1]) {
1308 case LEAF_begemotBridgeStpPortAdminEdgePort:
1309 bridge_port_set_admin_edge(b_name, bp,
1310 ctx->scratch->int1);
1311 break;
1312 case LEAF_begemotBridgeStpPortAdminPointToPoint:
1313 bridge_port_set_admin_p2p(b_name, bp,
1314 ctx->scratch->int1);
1315 break;
1316 case LEAF_begemotBridgeStpPortAdminPathCost:
1317 bridge_port_set_path_cost(b_name, bp,
1318 ctx->scratch->int1);
1319 break;
1320 }
1321 return (SNMP_ERR_NOERROR);
1322
1323 case SNMP_OP_COMMIT:
1324 return (SNMP_ERR_NOERROR);
1255 const char *b_name;
1256
1257 if (time(NULL) - ports_list_age > bridge_get_data_maxage())
1258 bridge_update_all_ports();
1259
1260 switch (op) {
1261 case SNMP_OP_GET:
1262 if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL)
1263 return (SNMP_ERR_NOSUCHNAME);
1264 break;
1265
1266 case SNMP_OP_GETNEXT:
1267 if ((bp = bridge_port_index_getnext(&val->var, sub, 0)) ==
1268 NULL || bridge_port_index_append(&val->var, sub, bp) < 0)
1269 return (SNMP_ERR_NOSUCHNAME);
1270 break;
1271
1272 case SNMP_OP_SET:
1273 if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL)
1274 return (SNMP_ERR_NOSUCHNAME);
1275 if ((b_name = bridge_if_find_name(bp->sysindex)) == NULL)
1276 return (SNMP_ERR_GENERR);
1277
1278 switch (val->var.subs[sub - 1]) {
1279 case LEAF_begemotBridgeStpPortAdminEdgePort:
1280 ctx->scratch->int1 = bp->admin_edge;
1281 ret = bridge_port_set_admin_edge(b_name, bp,
1282 val->v.integer);
1283 break;
1284 case LEAF_begemotBridgeStpPortAdminPointToPoint:
1285 ctx->scratch->int1 = bp->admin_p2p;
1286 ret = bridge_port_set_admin_p2p(b_name, bp,
1287 val->v.integer);
1288 break;
1289 case LEAF_begemotBridgeStpPortAdminPathCost:
1290 ctx->scratch->int1 = bp->admin_path_cost;
1291 ret = bridge_port_set_path_cost(b_name, bp,
1292 val->v.integer);
1293 break;
1294 case LEAF_begemotBridgeStpPortProtocolMigration:
1295 case LEAF_begemotBridgeStpPortOperEdgePort:
1296 case LEAF_begemotBridgeStpPortOperPointToPoint:
1297 return (SNMP_ERR_NOT_WRITEABLE);
1298 default:
1299 return (SNMP_ERR_NOSUCHNAME);
1300 }
1301
1302 if (ret == 0)
1303 return (SNMP_ERR_NOERROR);
1304 else if (ret == -2)
1305 return (SNMP_ERR_WRONG_VALUE);
1306 return (SNMP_ERR_GENERR);
1307
1308 case SNMP_OP_ROLLBACK:
1309 if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL ||
1310 (b_name = bridge_if_find_name(bp->sysindex)) == NULL)
1311 return (SNMP_ERR_GENERR);
1312
1313 switch (val->var.subs[sub - 1]) {
1314 case LEAF_begemotBridgeStpPortAdminEdgePort:
1315 bridge_port_set_admin_edge(b_name, bp,
1316 ctx->scratch->int1);
1317 break;
1318 case LEAF_begemotBridgeStpPortAdminPointToPoint:
1319 bridge_port_set_admin_p2p(b_name, bp,
1320 ctx->scratch->int1);
1321 break;
1322 case LEAF_begemotBridgeStpPortAdminPathCost:
1323 bridge_port_set_path_cost(b_name, bp,
1324 ctx->scratch->int1);
1325 break;
1326 }
1327 return (SNMP_ERR_NOERROR);
1328
1329 case SNMP_OP_COMMIT:
1330 return (SNMP_ERR_NOERROR);
1331
1332 default:
1333 abort();
1325 }
1326
1327 switch (val->var.subs[sub - 1]) {
1328 case LEAF_begemotBridgeStpPortProtocolMigration:
1329 val->v.integer = bp->proto_migr;
1330 break;
1331 case LEAF_begemotBridgeStpPortAdminEdgePort:
1332 val->v.integer = bp->admin_edge;
1333 break;
1334 case LEAF_begemotBridgeStpPortOperEdgePort:
1335 val->v.integer = bp->oper_edge;
1336 break;
1337 case LEAF_begemotBridgeStpPortAdminPointToPoint:
1338 val->v.integer = bp->admin_p2p;
1339 break;
1340 case LEAF_begemotBridgeStpPortOperPointToPoint:
1341 val->v.integer = bp->oper_p2p;
1342 break;
1343 case LEAF_begemotBridgeStpPortAdminPathCost:
1344 val->v.integer = bp->admin_path_cost;
1345 break;
1346 }
1347
1348 return (SNMP_ERR_NOERROR);
1349}
1350
1351int
1352op_begemot_tp_port(struct snmp_context *c __unused, struct snmp_value *val,
1353 uint sub, uint iidx __unused, enum snmp_op op)
1354{
1334 }
1335
1336 switch (val->var.subs[sub - 1]) {
1337 case LEAF_begemotBridgeStpPortProtocolMigration:
1338 val->v.integer = bp->proto_migr;
1339 break;
1340 case LEAF_begemotBridgeStpPortAdminEdgePort:
1341 val->v.integer = bp->admin_edge;
1342 break;
1343 case LEAF_begemotBridgeStpPortOperEdgePort:
1344 val->v.integer = bp->oper_edge;
1345 break;
1346 case LEAF_begemotBridgeStpPortAdminPointToPoint:
1347 val->v.integer = bp->admin_p2p;
1348 break;
1349 case LEAF_begemotBridgeStpPortOperPointToPoint:
1350 val->v.integer = bp->oper_p2p;
1351 break;
1352 case LEAF_begemotBridgeStpPortAdminPathCost:
1353 val->v.integer = bp->admin_path_cost;
1354 break;
1355 }
1356
1357 return (SNMP_ERR_NOERROR);
1358}
1359
1360int
1361op_begemot_tp_port(struct snmp_context *c __unused, struct snmp_value *val,
1362 uint sub, uint iidx __unused, enum snmp_op op)
1363{
1355 struct bridge_port *bp = NULL;
1364 struct bridge_port *bp;
1356
1357 if (time(NULL) - ports_list_age > bridge_get_data_maxage())
1358 bridge_update_all_ports();
1359
1360 switch (op) {
1361 case SNMP_OP_GET:
1362 if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL)
1363 return (SNMP_ERR_NOSUCHNAME);
1364 break;
1365
1366 case SNMP_OP_GETNEXT:
1367 if ((bp = bridge_port_index_getnext(&val->var, sub, 0)) ==
1368 NULL || bridge_port_index_append(&val->var, sub, bp) < 0)
1369 return (SNMP_ERR_NOSUCHNAME);
1370 break;
1371
1372 case SNMP_OP_SET:
1373 return (SNMP_ERR_NOT_WRITEABLE);
1374
1375 case SNMP_OP_ROLLBACK:
1376 case SNMP_OP_COMMIT:
1365
1366 if (time(NULL) - ports_list_age > bridge_get_data_maxage())
1367 bridge_update_all_ports();
1368
1369 switch (op) {
1370 case SNMP_OP_GET:
1371 if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL)
1372 return (SNMP_ERR_NOSUCHNAME);
1373 break;
1374
1375 case SNMP_OP_GETNEXT:
1376 if ((bp = bridge_port_index_getnext(&val->var, sub, 0)) ==
1377 NULL || bridge_port_index_append(&val->var, sub, bp) < 0)
1378 return (SNMP_ERR_NOSUCHNAME);
1379 break;
1380
1381 case SNMP_OP_SET:
1382 return (SNMP_ERR_NOT_WRITEABLE);
1383
1384 case SNMP_OP_ROLLBACK:
1385 case SNMP_OP_COMMIT:
1377 return (SNMP_ERR_NOERROR);
1386 default:
1387 abort();
1378 }
1379
1380 switch (val->var.subs[sub - 1]) {
1381 case LEAF_begemotBridgeTpPort:
1382 val->v.integer = bp->port_no;
1383 break;
1384 case LEAF_begemotBridgeTpPortMaxInfo:
1385 val->v.integer = bp->max_info;
1386 break;
1387 case LEAF_begemotBridgeTpPortInFrames:
1388 val->v.uint32 = bp->in_frames;
1389 break;
1390 case LEAF_begemotBridgeTpPortOutFrames:
1391 val->v.uint32 = bp->out_frames;
1392 break;
1393 case LEAF_begemotBridgeTpPortInDiscards:
1394 val->v.uint32 = bp->in_drops;
1395 break;
1396 }
1397
1398 return (SNMP_ERR_NOERROR);
1399}
1388 }
1389
1390 switch (val->var.subs[sub - 1]) {
1391 case LEAF_begemotBridgeTpPort:
1392 val->v.integer = bp->port_no;
1393 break;
1394 case LEAF_begemotBridgeTpPortMaxInfo:
1395 val->v.integer = bp->max_info;
1396 break;
1397 case LEAF_begemotBridgeTpPortInFrames:
1398 val->v.uint32 = bp->in_frames;
1399 break;
1400 case LEAF_begemotBridgeTpPortOutFrames:
1401 val->v.uint32 = bp->out_frames;
1402 break;
1403 case LEAF_begemotBridgeTpPortInDiscards:
1404 val->v.uint32 = bp->in_drops;
1405 break;
1406 }
1407
1408 return (SNMP_ERR_NOERROR);
1409}