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