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_if.c
106842 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 interface objects.
30
*/
31
32
#include <sys/queue.h>
33
#include <sys/socket.h>
34
#include <sys/time.h>
35
#include <sys/types.h>
36
37
#include <net/ethernet.h>
38
#include <net/if.h>
39
#include <net/if_mib.h>
40
#include <net/if_types.h>
41
42
#include <errno.h>
43
#include <stdarg.h>
44
#include <stdlib.h>
45
#include <string.h>
46
#include <syslog.h>
47
48
#include <bsnmp/snmpmod.h>
49
#include <bsnmp/snmp_mibII.h>
50
51
#define SNMPTREE_TYPES
52
#include "bridge_tree.h"
53
#include "bridge_snmp.h"
54
#include "bridge_oid.h"
55
56
static const struct asn_oid oid_newRoot = OIDX_newRoot;
57
static const struct asn_oid oid_TopologyChange = OIDX_topologyChange;
58
static const struct asn_oid oid_begemotBrigeName = \
59
OIDX_begemotBridgeBaseName;
60
static const struct asn_oid oid_begemotNewRoot = OIDX_begemotBridgeNewRoot;
61
static const struct asn_oid oid_begemotTopologyChange = \
62
OIDX_begemotBridgeTopologyChange;
63
64
TAILQ_HEAD(bridge_ifs, bridge_if);
65
66
/*
67
* Free the bridge interface list.
68
*/
69
static void
70
bridge_ifs_free(struct bridge_ifs *headp)
71
{
72
struct bridge_if *b;
73
74
while ((b = TAILQ_FIRST(headp)) != NULL) {
75
TAILQ_REMOVE(headp, b, b_if);
76
free(b);
77
}
78
}
79
80
/*
81
* Insert an entry in the bridge interface TAILQ. Keep the
82
* TAILQ sorted by the bridge's interface name.
83
*/
84
static void
85
bridge_ifs_insert(struct bridge_ifs *headp,
86
struct bridge_if *b)
87
{
88
struct bridge_if *temp;
89
90
if ((temp = TAILQ_FIRST(headp)) == NULL ||
91
strcmp(b->bif_name, temp->bif_name) < 0) {
92
TAILQ_INSERT_HEAD(headp, b, b_if);
93
return;
94
}
95
96
TAILQ_FOREACH(temp, headp, b_if)
97
if(strcmp(b->bif_name, temp->bif_name) < 0)
98
TAILQ_INSERT_BEFORE(temp, b, b_if);
99
100
TAILQ_INSERT_TAIL(headp, b, b_if);
101
}
102
103
/* The global bridge interface list. */
104
static struct bridge_ifs bridge_ifs = TAILQ_HEAD_INITIALIZER(bridge_ifs);
105
static time_t bridge_list_age;
106
107
/*
108
* Free the global list.
109
*/
110
void
111
bridge_ifs_fini(void)
112
{
113
bridge_ifs_free(&bridge_ifs);
114
}
115
116
/*
117
* Find a bridge interface entry by the bridge interface system index.
118
*/
119
struct bridge_if *
120
bridge_if_find_ifs(uint32_t sysindex)
121
{
122
struct bridge_if *b;
123
124
TAILQ_FOREACH(b, &bridge_ifs, b_if)
125
if (b->sysindex == sysindex)
126
return (b);
127
128
return (NULL);
129
}
130
131
/*
132
* Find a bridge interface entry by the bridge interface name.
133
*/
134
struct bridge_if *
135
bridge_if_find_ifname(const char *b_name)
136
{
137
struct bridge_if *b;
138
139
TAILQ_FOREACH(b, &bridge_ifs, b_if)
140
if (strcmp(b_name, b->bif_name) == 0)
141
return (b);
142
143
return (NULL);
144
}
145
146
/*
147
* Find a bridge name by the bridge interface system index.
148
*/
149
const char *
150
bridge_if_find_name(uint32_t sysindex)
151
{
152
struct bridge_if *b;
153
154
TAILQ_FOREACH(b, &bridge_ifs, b_if)
155
if (b->sysindex == sysindex)
156
return (b->bif_name);
157
158
return (NULL);
159
}
160
161
/*
162
* Given two bridge interfaces' system indexes, find their
163
* corresponding names and return the result of the name
164
* comparison. Returns:
165
* error : -2
166
* i1 < i2 : -1
167
* i1 > i2 : +1
168
* i1 = i2 : 0
169
*/
170
int
171
bridge_compare_sysidx(uint32_t i1, uint32_t i2)
172
{
173
int c;
174
const char *b1, *b2;
175
176
if (i1 == i2)
177
return (0);
178
179
if ((b1 = bridge_if_find_name(i1)) == NULL) {
180
syslog(LOG_ERR, "Bridge interface %d does not exist", i1);
181
return (-2);
182
}
183
184
if ((b2 = bridge_if_find_name(i2)) == NULL) {
185
syslog(LOG_ERR, "Bridge interface %d does not exist", i2);
186
return (-2);
187
}
188
189
if ((c = strcmp(b1, b2)) < 0)
190
return (-1);
191
else if (c > 0)
192
return (1);
193
194
return (0);
195
}
196
197
/*
198
* Fetch the first bridge interface from the list.
199
*/
200
struct bridge_if *
201
bridge_first_bif(void)
202
{
203
return (TAILQ_FIRST(&bridge_ifs));
204
}
205
206
/*
207
* Fetch the next bridge interface from the list.
208
*/
209
struct bridge_if *
210
bridge_next_bif(struct bridge_if *b_pr)
211
{
212
return (TAILQ_NEXT(b_pr, b_if));
213
}
214
215
/*
216
* Create a new entry for a bridge interface and insert
217
* it in the list.
218
*/
219
static struct bridge_if *
220
bridge_new_bif(const char *bif_n, uint32_t sysindex, const u_char *physaddr)
221
{
222
struct bridge_if *bif;
223
224
if ((bif = (struct bridge_if *) malloc(sizeof(*bif)))== NULL) {
225
syslog(LOG_ERR, "bridge new interface failed: %s",
226
strerror(errno));
227
return (NULL);
228
}
229
230
bzero(bif, sizeof(struct bridge_if));
231
strlcpy(bif->bif_name, bif_n, IFNAMSIZ);
232
bcopy(physaddr, bif->br_addr.octet, ETHER_ADDR_LEN);
233
bif->sysindex = sysindex;
234
bif->br_type = BaseType_transparent_only;
235
/* 1 - all bridges default hold time * 100 - centi-seconds */
236
bif->hold_time = 1 * 100;
237
bif->prot_spec = dot1dStpProtocolSpecification_ieee8021d;
238
bridge_ifs_insert(&bridge_ifs, bif);
239
240
return (bif);
241
}
242
243
/*
244
* Remove a bridge interface from the list, freeing all it's ports
245
* and address entries.
246
*/
247
void
248
bridge_remove_bif(struct bridge_if *bif)
249
{
250
bridge_members_free(bif);
251
bridge_addrs_free(bif);
252
TAILQ_REMOVE(&bridge_ifs, bif, b_if);
253
free(bif);
254
}
255
256
257
/*
258
* Prepare the variable (bridge interface name) for the private
259
* begemot notifications.
260
*/
261
static struct snmp_value*
262
bridge_basename_var(struct bridge_if *bif, struct snmp_value* b_val)
263
{
264
uint i;
265
266
b_val->var = oid_begemotBrigeName;
267
b_val->var.subs[b_val->var.len++] = strlen(bif->bif_name);
268
269
if ((b_val->v.octetstring.octets = (u_char *)
270
malloc(strlen(bif->bif_name))) == NULL)
271
return (NULL);
272
273
for (i = 0; i < strlen(bif->bif_name); i++)
274
b_val->var.subs[b_val->var.len++] = bif->bif_name[i];
275
276
b_val->v.octetstring.len = strlen(bif->bif_name);
277
bcopy(bif->bif_name, b_val->v.octetstring.octets,
278
strlen(bif->bif_name));
279
b_val->syntax = SNMP_SYNTAX_OCTETSTRING;
280
281
return (b_val);
282
}
283
284
/*
285
* Compare the values of the old and the new root port and
286
* send a new root notification, if they are not matching.
287
*/
288
static void
289
bridge_new_root(struct bridge_if *bif)
290
{
291
struct snmp_value bif_idx;
292
293
if (bridge_get_default() == bif)
294
snmp_send_trap(&oid_newRoot, (struct snmp_value *) NULL);
295
296
if (bridge_basename_var(bif, &bif_idx) == NULL)
297
return;
298
299
snmp_send_trap(&oid_begemotTopologyChange,
300
&bif_idx, (struct snmp_value *) NULL);
301
}
302
303
/*
304
* Compare the new and old topology change times and send a
305
* topology change notification if necessary.
306
*/
307
static void
308
bridge_top_change(struct bridge_if *bif)
309
{
310
struct snmp_value bif_idx;
311
312
if (bridge_get_default() == bif)
313
snmp_send_trap(&oid_TopologyChange,
314
(struct snmp_value *) NULL);
315
316
if (bridge_basename_var(bif, &bif_idx) == NULL)
317
return;
318
319
snmp_send_trap(&oid_begemotNewRoot,
320
&bif_idx, (struct snmp_value *) NULL);
321
}
322
323
static int
324
bridge_if_create(const char* b_name, int8_t up)
325
{
326
if (bridge_create(b_name) < 0)
327
return (-1);
328
329
if (up == 1 && (bridge_set_if_up(b_name, 1) < 0))
330
return (-1);
331
332
/*
333
* Do not create a new bridge entry here -
334
* wait until the mibII module notifies us.
335
*/
336
return (0);
337
}
338
339
static int
340
bridge_if_destroy(struct bridge_if *bif)
341
{
342
if (bridge_destroy(bif->bif_name) < 0)
343
return (-1);
344
345
bridge_remove_bif(bif);
346
347
return (0);
348
}
349
350
/*
351
* Calculate the timeticks since the last topology change.
352
*/
353
static int
354
bridge_get_time_since_tc(struct bridge_if *bif, uint32_t *ticks)
355
{
356
struct timeval ct;
357
358
if (gettimeofday(&ct, NULL) < 0) {
359
syslog(LOG_ERR, "bridge get time since last TC:"
360
"gettimeofday failed: %s", strerror(errno));
361
return (-1);
362
}
363
364
if (ct.tv_usec - bif->last_tc_time.tv_usec < 0) {
365
ct.tv_sec -= 1;
366
ct.tv_usec += 1000000;
367
}
368
369
ct.tv_sec -= bif->last_tc_time.tv_sec;
370
ct.tv_usec -= bif->last_tc_time.tv_usec;
371
372
*ticks = ct.tv_sec * 100 + ct.tv_usec/10000;
373
374
return (0);
375
}
376
377
/*
378
* Update the info we have for a single bridge interface.
379
* Return:
380
* 1, if successful
381
* 0, if the interface was deleted
382
* -1, error occurred while fetching the info from the kernel.
383
*/
384
static int
385
bridge_update_bif(struct bridge_if *bif)
386
{
387
struct mibif *ifp;
388
389
/* Walk through the mibII interface list. */
390
for (ifp = mib_first_if(); ifp != NULL; ifp = mib_next_if(ifp))
391
if (strcmp(ifp->name, bif->bif_name) == 0)
392
break;
393
394
if (ifp == NULL) {
395
/* Ops, we do not exist anymore. */
396
bridge_remove_bif(bif);
397
return (0);
398
}
399
400
if (ifp->physaddr != NULL )
401
bcopy(ifp->physaddr, bif->br_addr.octet, ETHER_ADDR_LEN);
402
else
403
bridge_get_basemac(bif->bif_name, bif->br_addr.octet,
404
ETHER_ADDR_LEN);
405
406
if (ifp->mib.ifmd_flags & IFF_RUNNING)
407
bif->if_status = RowStatus_active;
408
else
409
bif->if_status = RowStatus_notInService;
410
411
switch (bridge_getinfo_bif(bif)) {
412
case 2:
413
bridge_new_root(bif);
414
break;
415
case 1:
416
bridge_top_change(bif);
417
break;
418
case -1:
419
bridge_remove_bif(bif);
420
return (-1);
421
default:
422
break;
423
}
424
425
/*
426
* The number of ports is accessible via SNMP -
427
* update the ports each time the bridge interface data
428
* is refreshed too.
429
*/
430
bif->num_ports = bridge_update_memif(bif);
431
bif->entry_age = time(NULL);
432
433
return (1);
434
}
435
436
/*
437
* Update all bridge interfaces' ports only -
438
* make sure each bridge interface exists first.
439
*/
440
void
441
bridge_update_all_ports(void)
442
{
443
struct mibif *ifp;
444
struct bridge_if *bif, *t_bif;
445
446
for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) {
447
t_bif = bridge_next_bif(bif);
448
449
for (ifp = mib_first_if(); ifp != NULL;
450
ifp = mib_next_if(ifp))
451
if (strcmp(ifp->name, bif->bif_name) == 0)
452
break;
453
454
if (ifp != NULL)
455
bif->num_ports = bridge_update_memif(bif);
456
else /* Ops, we do not exist anymore. */
457
bridge_remove_bif(bif);
458
}
459
460
bridge_ports_update_listage();
461
}
462
463
/*
464
* Update all addresses only.
465
*/
466
void
467
bridge_update_all_addrs(void)
468
{
469
struct mibif *ifp;
470
struct bridge_if *bif, *t_bif;
471
472
for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) {
473
t_bif = bridge_next_bif(bif);
474
475
for (ifp = mib_first_if(); ifp != NULL;
476
ifp = mib_next_if(ifp))
477
if (strcmp(ifp->name, bif->bif_name) == 0)
478
break;
479
480
if (ifp != NULL)
481
bif->num_addrs = bridge_update_addrs(bif);
482
else /* Ops, we don't exist anymore. */
483
bridge_remove_bif(bif);
484
}
485
486
bridge_addrs_update_listage();
487
}
488
489
/*
490
* Update only the bridge interfaces' data - skip addresses.
491
*/
492
void
493
bridge_update_all_ifs(void)
494
{
495
struct bridge_if *bif, *t_bif;
496
497
for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) {
498
t_bif = bridge_next_bif(bif);
499
bridge_update_bif(bif);
500
}
501
502
bridge_ports_update_listage();
503
bridge_list_age = time(NULL);
504
}
505
506
/*
507
* Update all info we have for all bridges.
508
*/
509
void
510
bridge_update_all(void *arg __unused)
511
{
512
struct bridge_if *bif, *t_bif;
513
514
for (bif = bridge_first_bif(); bif != NULL; bif = t_bif) {
515
t_bif = bridge_next_bif(bif);
516
if (bridge_update_bif(bif) <= 0)
517
continue;
518
519
/* Update our learnt addresses. */
520
bif->num_addrs = bridge_update_addrs(bif);
521
}
522
523
bridge_list_age = time(NULL);
524
bridge_ports_update_listage();
525
bridge_addrs_update_listage();
526
}
527
528
/*
529
* Callback for polling our last topology change time -
530
* check whether we are root or whether a TC was detected once every
531
* 30 seconds, so that we can send the newRoot and TopologyChange traps
532
* on time. The rest of the data is polled only once every 5 min.
533
*/
534
void
535
bridge_update_tc_time(void *arg __unused)
536
{
537
struct bridge_if *bif;
538
struct mibif *ifp;
539
540
TAILQ_FOREACH(bif, &bridge_ifs, b_if) {
541
/* Walk through the mibII interface list. */
542
for (ifp = mib_first_if(); ifp != NULL; ifp = mib_next_if(ifp))
543
if (strcmp(ifp->name, bif->bif_name) == 0)
544
break;
545
546
if (ifp == NULL) {
547
bridge_remove_bif(bif);
548
continue;
549
}
550
551
switch (bridge_get_op_param(bif)) {
552
case 2:
553
bridge_new_root(bif);
554
break;
555
case 1:
556
bridge_top_change(bif);
557
break;
558
}
559
}
560
}
561
562
/*
563
* Callback for handling new bridge interface creation.
564
*/
565
int
566
bridge_attach_newif(struct mibif *ifp)
567
{
568
u_char mac[ETHER_ADDR_LEN];
569
struct bridge_if *bif;
570
571
if (ifp->mib.ifmd_data.ifi_type != IFT_BRIDGE)
572
return (0);
573
574
/* Make sure it does not exist in our list. */
575
TAILQ_FOREACH(bif, &bridge_ifs, b_if)
576
if(strcmp(bif->bif_name, ifp->name) == 0) {
577
syslog(LOG_ERR, "bridge interface %s already "
578
"in list", bif->bif_name);
579
return (-1);
580
}
581
582
if (ifp->physaddr == NULL) {
583
if (bridge_get_basemac(ifp->name, mac, sizeof(mac)) == NULL) {
584
syslog(LOG_ERR, "bridge attach new %s failed - "
585
"no bridge mac address", ifp->name);
586
return (-1);
587
}
588
} else
589
bcopy(ifp->physaddr, &mac, sizeof(mac));
590
591
if ((bif = bridge_new_bif(ifp->name, ifp->sysindex, mac)) == NULL)
592
return (-1);
593
594
if (ifp->mib.ifmd_flags & IFF_RUNNING)
595
bif->if_status = RowStatus_active;
596
else
597
bif->if_status = RowStatus_notInService;
598
599
/* Skip sending notifications if the interface was just created. */
600
if (bridge_getinfo_bif(bif) < 0 ||
601
(bif->num_ports = bridge_getinfo_bif_ports(bif)) < 0 ||
602
(bif->num_addrs = bridge_getinfo_bif_addrs(bif)) < 0) {
603
bridge_remove_bif(bif);
604
return (-1);
605
}
606
607
/* Check whether we are the default bridge interface. */
608
if (strcmp(ifp->name, bridge_get_default_name()) == 0)
609
bridge_set_default(bif);
610
611
return (0);
612
}
613
614
void
615
bridge_ifs_dump(void)
616
{
617
struct bridge_if *bif;
618
619
for (bif = bridge_first_bif(); bif != NULL;
620
bif = bridge_next_bif(bif)) {
621
syslog(LOG_ERR, "Bridge %s, index - %d", bif->bif_name,
622
bif->sysindex);
623
bridge_ports_dump(bif);
624
bridge_addrs_dump(bif);
625
}
626
}
627
628
/*
629
* RFC4188 specifics.
630
*/
631
int
632
op_dot1d_base(struct snmp_context *ctx __unused, struct snmp_value *value,
633
uint sub, uint iidx __unused, enum snmp_op op)
634
{
635
struct bridge_if *bif;
636
637
if ((bif = bridge_get_default()) == NULL)
638
return (SNMP_ERR_NOSUCHNAME);
639
640
if (time(NULL) - bif->entry_age > bridge_get_data_maxage() &&
641
bridge_update_bif(bif) <= 0) /* It was just deleted. */
642
return (SNMP_ERR_NOSUCHNAME);
643
644
switch (op) {
645
case SNMP_OP_GET:
646
switch (value->var.subs[sub - 1]) {
647
case LEAF_dot1dBaseBridgeAddress:
648
return (string_get(value, bif->br_addr.octet,
649
ETHER_ADDR_LEN));
650
case LEAF_dot1dBaseNumPorts:
651
value->v.integer = bif->num_ports;
652
return (SNMP_ERR_NOERROR);
653
case LEAF_dot1dBaseType:
654
value->v.integer = bif->br_type;
655
return (SNMP_ERR_NOERROR);
656
}
657
abort();
658
659
case SNMP_OP_SET:
660
return (SNMP_ERR_NOT_WRITEABLE);
661
662
case SNMP_OP_GETNEXT:
663
case SNMP_OP_ROLLBACK:
664
case SNMP_OP_COMMIT:
665
break;
666
}
667
668
abort();
669
}
670
671
int
672
op_dot1d_stp(struct snmp_context *ctx, struct snmp_value *val, uint sub,
673
uint iidx __unused, enum snmp_op op)
674
{
675
struct bridge_if *bif;
676
677
if ((bif = bridge_get_default()) == NULL)
678
return (SNMP_ERR_NOSUCHNAME);
679
680
if (time(NULL) - bif->entry_age > bridge_get_data_maxage() &&
681
bridge_update_bif(bif) <= 0) /* It was just deleted. */
682
return (SNMP_ERR_NOSUCHNAME);
683
684
switch (op) {
685
case SNMP_OP_GET:
686
switch (val->var.subs[sub - 1]) {
687
case LEAF_dot1dStpProtocolSpecification:
688
val->v.integer = bif->prot_spec;
689
return (SNMP_ERR_NOERROR);
690
691
case LEAF_dot1dStpPriority:
692
val->v.integer = bif->priority;
693
return (SNMP_ERR_NOERROR);
694
695
case LEAF_dot1dStpTimeSinceTopologyChange:
696
if (bridge_get_time_since_tc(bif,
697
&(val->v.uint32)) < 0)
698
return (SNMP_ERR_GENERR);
699
return (SNMP_ERR_NOERROR);
700
701
case LEAF_dot1dStpTopChanges:
702
val->v.uint32 = bif->top_changes;
703
return (SNMP_ERR_NOERROR);
704
705
case LEAF_dot1dStpDesignatedRoot:
706
return (string_get(val, bif->design_root,
707
SNMP_BRIDGE_ID_LEN));
708
709
case LEAF_dot1dStpRootCost:
710
val->v.integer = bif->root_cost;
711
return (SNMP_ERR_NOERROR);
712
713
case LEAF_dot1dStpRootPort:
714
val->v.integer = bif->root_port;
715
return (SNMP_ERR_NOERROR);
716
717
case LEAF_dot1dStpMaxAge:
718
val->v.integer = bif->max_age;
719
return (SNMP_ERR_NOERROR);
720
721
case LEAF_dot1dStpHelloTime:
722
val->v.integer = bif->hello_time;
723
return (SNMP_ERR_NOERROR);
724
725
case LEAF_dot1dStpHoldTime:
726
val->v.integer = bif->hold_time;
727
return (SNMP_ERR_NOERROR);
728
729
case LEAF_dot1dStpForwardDelay:
730
val->v.integer = bif->fwd_delay;
731
return (SNMP_ERR_NOERROR);
732
733
case LEAF_dot1dStpBridgeMaxAge:
734
val->v.integer = bif->bridge_max_age;
735
return (SNMP_ERR_NOERROR);
736
737
case LEAF_dot1dStpBridgeHelloTime:
738
val->v.integer = bif->bridge_hello_time;
739
return (SNMP_ERR_NOERROR);
740
741
case LEAF_dot1dStpBridgeForwardDelay:
742
val->v.integer = bif->bridge_fwd_delay;
743
return (SNMP_ERR_NOERROR);
744
745
case LEAF_dot1dStpVersion:
746
val->v.integer = bif->stp_version;
747
return (SNMP_ERR_NOERROR);
748
749
case LEAF_dot1dStpTxHoldCount:
750
val->v.integer = bif->tx_hold_count;
751
return (SNMP_ERR_NOERROR);
752
}
753
abort();
754
755
case SNMP_OP_GETNEXT:
756
abort();
757
758
case SNMP_OP_SET:
759
switch (val->var.subs[sub - 1]) {
760
case LEAF_dot1dStpPriority:
761
if (val->v.integer > SNMP_BRIDGE_MAX_PRIORITY ||
762
val->v.integer % 4096 != 0)
763
return (SNMP_ERR_WRONG_VALUE);
764
765
ctx->scratch->int1 = bif->priority;
766
if (bridge_set_priority(bif, val->v.integer) < 0)
767
return (SNMP_ERR_GENERR);
768
return (SNMP_ERR_NOERROR);
769
770
case LEAF_dot1dStpBridgeMaxAge:
771
if (val->v.integer < SNMP_BRIDGE_MIN_MAGE ||
772
val->v.integer > SNMP_BRIDGE_MAX_MAGE)
773
return (SNMP_ERR_WRONG_VALUE);
774
775
ctx->scratch->int1 = bif->bridge_max_age;
776
if (bridge_set_maxage(bif, val->v.integer) < 0)
777
return (SNMP_ERR_GENERR);
778
return (SNMP_ERR_NOERROR);
779
780
case LEAF_dot1dStpBridgeHelloTime:
781
if (val->v.integer < SNMP_BRIDGE_MIN_HTIME ||
782
val->v.integer > SNMP_BRIDGE_MAX_HTIME)
783
return (SNMP_ERR_WRONG_VALUE);
784
785
ctx->scratch->int1 = bif->bridge_hello_time;
786
if (bridge_set_hello_time(bif, val->v.integer) < 0)
787
return (SNMP_ERR_GENERR);
788
return (SNMP_ERR_NOERROR);
789
790
case LEAF_dot1dStpBridgeForwardDelay:
791
if (val->v.integer < SNMP_BRIDGE_MIN_FDELAY ||
792
val->v.integer > SNMP_BRIDGE_MAX_FDELAY)
793
return (SNMP_ERR_WRONG_VALUE);
794
795
ctx->scratch->int1 = bif->bridge_fwd_delay;
796
if (bridge_set_forward_delay(bif, val->v.integer) < 0)
797
return (SNMP_ERR_GENERR);
798
return (SNMP_ERR_NOERROR);
799
800
case LEAF_dot1dStpVersion:
801
if (val->v.integer != dot1dStpVersion_stpCompatible &&
802
val->v.integer != dot1dStpVersion_rstp)
803
return (SNMP_ERR_WRONG_VALUE);
804
805
ctx->scratch->int1 = bif->stp_version;
806
if (bridge_set_stp_version(bif, val->v.integer) < 0)
807
return (SNMP_ERR_GENERR);
808
return (SNMP_ERR_NOERROR);
809
810
case LEAF_dot1dStpTxHoldCount:
811
if (val->v.integer < SNMP_BRIDGE_MIN_TXHC ||
812
val->v.integer > SNMP_BRIDGE_MAX_TXHC)
813
return (SNMP_ERR_WRONG_VALUE);
814
815
ctx->scratch->int1 = bif->tx_hold_count;
816
if (bridge_set_tx_hold_count(bif, val->v.integer) < 0)
817
return (SNMP_ERR_GENERR);
818
return (SNMP_ERR_NOERROR);
819
820
case LEAF_dot1dStpProtocolSpecification:
821
case LEAF_dot1dStpTimeSinceTopologyChange:
822
case LEAF_dot1dStpTopChanges:
823
case LEAF_dot1dStpDesignatedRoot:
824
case LEAF_dot1dStpRootCost:
825
case LEAF_dot1dStpRootPort:
826
case LEAF_dot1dStpMaxAge:
827
case LEAF_dot1dStpHelloTime:
828
case LEAF_dot1dStpHoldTime:
829
case LEAF_dot1dStpForwardDelay:
830
return (SNMP_ERR_NOT_WRITEABLE);
831
}
832
abort();
833
834
case SNMP_OP_ROLLBACK:
835
switch (val->var.subs[sub - 1]) {
836
case LEAF_dot1dStpPriority:
837
bridge_set_priority(bif, ctx->scratch->int1);
838
break;
839
case LEAF_dot1dStpBridgeMaxAge:
840
bridge_set_maxage(bif, ctx->scratch->int1);
841
break;
842
case LEAF_dot1dStpBridgeHelloTime:
843
bridge_set_hello_time(bif, ctx->scratch->int1);
844
break;
845
case LEAF_dot1dStpBridgeForwardDelay:
846
bridge_set_forward_delay(bif, ctx->scratch->int1);
847
break;
848
case LEAF_dot1dStpVersion:
849
bridge_set_stp_version(bif, ctx->scratch->int1);
850
break;
851
case LEAF_dot1dStpTxHoldCount:
852
bridge_set_tx_hold_count(bif, ctx->scratch->int1);
853
break;
854
}
855
return (SNMP_ERR_NOERROR);
856
857
case SNMP_OP_COMMIT:
858
return (SNMP_ERR_NOERROR);
859
}
860
861
abort();
862
}
863
864
int
865
op_dot1d_tp(struct snmp_context *ctx, struct snmp_value *value,
866
uint sub, uint iidx __unused, enum snmp_op op)
867
{
868
struct bridge_if *bif;
869
870
if ((bif = bridge_get_default()) == NULL)
871
return (SNMP_ERR_NOSUCHNAME);
872
873
if (time(NULL) - bif->entry_age > bridge_get_data_maxage() &&
874
bridge_update_bif(bif) <= 0) /* It was just deleted. */
875
return (SNMP_ERR_NOSUCHNAME);
876
877
switch (op) {
878
case SNMP_OP_GET:
879
switch (value->var.subs[sub - 1]) {
880
case LEAF_dot1dTpLearnedEntryDiscards:
881
value->v.uint32 = bif->lrnt_drops;
882
return (SNMP_ERR_NOERROR);
883
case LEAF_dot1dTpAgingTime:
884
value->v.integer = bif->age_time;
885
return (SNMP_ERR_NOERROR);
886
}
887
abort();
888
889
case SNMP_OP_GETNEXT:
890
abort();
891
892
case SNMP_OP_SET:
893
switch (value->var.subs[sub - 1]) {
894
case LEAF_dot1dTpLearnedEntryDiscards:
895
return (SNMP_ERR_NOT_WRITEABLE);
896
897
case LEAF_dot1dTpAgingTime:
898
if (value->v.integer < SNMP_BRIDGE_MIN_AGE_TIME ||
899
value->v.integer > SNMP_BRIDGE_MAX_AGE_TIME)
900
return (SNMP_ERR_WRONG_VALUE);
901
902
ctx->scratch->int1 = bif->age_time;
903
if (bridge_set_aging_time(bif, value->v.integer) < 0)
904
return (SNMP_ERR_GENERR);
905
return (SNMP_ERR_NOERROR);
906
}
907
abort();
908
909
case SNMP_OP_ROLLBACK:
910
if (value->var.subs[sub - 1] == LEAF_dot1dTpAgingTime)
911
bridge_set_aging_time(bif, ctx->scratch->int1);
912
return (SNMP_ERR_NOERROR);
913
914
case SNMP_OP_COMMIT:
915
return (SNMP_ERR_NOERROR);
916
}
917
918
abort();
919
}
920
921
/*
922
* Private BEGEMOT-BRIDGE-MIB specifics.
923
*/
924
925
/*
926
* Get the bridge name from an OID index.
927
*/
928
static char *
929
bridge_name_index_get(const struct asn_oid *oid, uint sub, char *b_name)
930
{
931
uint i;
932
933
if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ)
934
return (NULL);
935
936
for (i = 0; i < oid->subs[sub]; i++)
937
b_name[i] = oid->subs[sub + i + 1];
938
b_name[i] = '\0';
939
940
return (b_name);
941
}
942
943
static void
944
bridge_if_index_append(struct asn_oid *oid, uint sub,
945
const struct bridge_if *bif)
946
{
947
uint i;
948
949
oid->len = sub + strlen(bif->bif_name) + 1;
950
oid->subs[sub] = strlen(bif->bif_name);
951
952
for (i = 1; i <= strlen(bif->bif_name); i++)
953
oid->subs[sub + i] = bif->bif_name[i - 1];
954
}
955
956
static struct bridge_if *
957
bridge_if_index_get(const struct asn_oid *oid, uint sub)
958
{
959
uint i;
960
char bif_name[IFNAMSIZ];
961
962
if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ)
963
return (NULL);
964
965
for (i = 0; i < oid->subs[sub]; i++)
966
bif_name[i] = oid->subs[sub + i + 1];
967
bif_name[i] = '\0';
968
969
return (bridge_if_find_ifname(bif_name));
970
}
971
972
static struct bridge_if *
973
bridge_if_index_getnext(const struct asn_oid *oid, uint sub)
974
{
975
uint i;
976
char bif_name[IFNAMSIZ];
977
struct bridge_if *bif;
978
979
if (oid->len - sub == 0)
980
return (bridge_first_bif());
981
982
if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= IFNAMSIZ)
983
return (NULL);
984
985
for (i = 0; i < oid->subs[sub]; i++)
986
bif_name[i] = oid->subs[sub + i + 1];
987
bif_name[i] = '\0';
988
989
if ((bif = bridge_if_find_ifname(bif_name)) == NULL)
990
return (NULL);
991
992
return (bridge_next_bif(bif));
993
}
994
995
static int
996
bridge_set_if_status(struct snmp_context *ctx,
997
struct snmp_value *val, uint sub)
998
{
999
struct bridge_if *bif;
1000
char bif_name[IFNAMSIZ];
1001
1002
bif = bridge_if_index_get(&val->var, sub);
1003
1004
switch (val->v.integer) {
1005
case RowStatus_active:
1006
if (bif == NULL)
1007
return (SNMP_ERR_INCONS_VALUE);
1008
1009
ctx->scratch->int1 = bif->if_status;
1010
1011
switch (bif->if_status) {
1012
case RowStatus_active:
1013
return (SNMP_ERR_NOERROR);
1014
case RowStatus_notInService:
1015
if (bridge_set_if_up(bif->bif_name, 1) < 0)
1016
return (SNMP_ERR_GENERR);
1017
return (SNMP_ERR_NOERROR);
1018
default:
1019
break;
1020
}
1021
return (SNMP_ERR_INCONS_VALUE);
1022
1023
case RowStatus_notInService:
1024
if (bif == NULL)
1025
return (SNMP_ERR_INCONS_VALUE);
1026
1027
ctx->scratch->int1 = bif->if_status;
1028
1029
switch (bif->if_status) {
1030
case RowStatus_active:
1031
if (bridge_set_if_up(bif->bif_name, 1) < 0)
1032
return (SNMP_ERR_GENERR);
1033
return (SNMP_ERR_NOERROR);
1034
case RowStatus_notInService:
1035
return (SNMP_ERR_NOERROR);
1036
default:
1037
break;
1038
}
1039
return (SNMP_ERR_INCONS_VALUE);
1040
1041
case RowStatus_notReady:
1042
return (SNMP_ERR_INCONS_VALUE);
1043
1044
case RowStatus_createAndGo:
1045
if (bif != NULL)
1046
return (SNMP_ERR_INCONS_VALUE);
1047
1048
ctx->scratch->int1 = RowStatus_destroy;
1049
1050
if (bridge_name_index_get(&val->var, sub, bif_name) == NULL)
1051
return (SNMP_ERR_BADVALUE);
1052
if (bridge_if_create(bif_name, 1) < 0)
1053
return (SNMP_ERR_GENERR);
1054
return (SNMP_ERR_NOERROR);
1055
1056
case RowStatus_createAndWait:
1057
if (bif != NULL)
1058
return (SNMP_ERR_INCONS_VALUE);
1059
1060
if (bridge_name_index_get(&val->var, sub, bif_name) == NULL)
1061
return (SNMP_ERR_BADVALUE);
1062
1063
ctx->scratch->int1 = RowStatus_destroy;
1064
1065
if (bridge_if_create(bif_name, 0) < 0)
1066
return (SNMP_ERR_GENERR);
1067
return (SNMP_ERR_NOERROR);
1068
1069
case RowStatus_destroy:
1070
if (bif == NULL)
1071
return (SNMP_ERR_NOSUCHNAME);
1072
1073
ctx->scratch->int1 = bif->if_status;
1074
bif->if_status = RowStatus_destroy;
1075
}
1076
1077
return (SNMP_ERR_NOERROR);
1078
}
1079
1080
static int
1081
bridge_rollback_if_status(struct snmp_context *ctx,
1082
struct snmp_value *val, uint sub)
1083
{
1084
struct bridge_if *bif;
1085
1086
if ((bif = bridge_if_index_get(&val->var, sub)) == NULL)
1087
return (SNMP_ERR_GENERR);
1088
1089
switch (ctx->scratch->int1) {
1090
case RowStatus_destroy:
1091
bridge_if_destroy(bif);
1092
return (SNMP_ERR_NOERROR);
1093
1094
case RowStatus_notInService:
1095
if (bif->if_status != ctx->scratch->int1)
1096
bridge_set_if_up(bif->bif_name, 0);
1097
bif->if_status = RowStatus_notInService;
1098
return (SNMP_ERR_NOERROR);
1099
1100
case RowStatus_active:
1101
if (bif->if_status != ctx->scratch->int1)
1102
bridge_set_if_up(bif->bif_name, 1);
1103
bif->if_status = RowStatus_active;
1104
return (SNMP_ERR_NOERROR);
1105
}
1106
1107
abort();
1108
}
1109
1110
static int
1111
bridge_commit_if_status(struct snmp_value *val, uint sub)
1112
{
1113
struct bridge_if *bif;
1114
1115
if ((bif = bridge_if_index_get(&val->var, sub)) == NULL)
1116
return (SNMP_ERR_GENERR);
1117
1118
if (bif->if_status == RowStatus_destroy &&
1119
bridge_if_destroy(bif) < 0)
1120
return (SNMP_ERR_COMMIT_FAILED);
1121
1122
return (SNMP_ERR_NOERROR);
1123
}
1124
1125
int
1126
op_begemot_base_bridge(struct snmp_context *ctx, struct snmp_value *val,
1127
uint sub, uint iidx __unused, enum snmp_op op)
1128
{
1129
struct bridge_if *bif;
1130
1131
if (time(NULL) - bridge_list_age > bridge_get_data_maxage())
1132
bridge_update_all_ifs();
1133
1134
switch (op) {
1135
case SNMP_OP_GET:
1136
if ((bif = bridge_if_index_get(&val->var, sub)) == NULL)
1137
return (SNMP_ERR_NOSUCHNAME);
1138
goto get;
1139
1140
case SNMP_OP_GETNEXT:
1141
if ((bif = bridge_if_index_getnext(&val->var, sub)) == NULL)
1142
return (SNMP_ERR_NOSUCHNAME);
1143
bridge_if_index_append(&val->var, sub, bif);
1144
goto get;
1145
1146
case SNMP_OP_SET:
1147
switch (val->var.subs[sub - 1]) {
1148
case LEAF_begemotBridgeBaseStatus:
1149
return (bridge_set_if_status(ctx, val, sub));
1150
case LEAF_begemotBridgeBaseName:
1151
case LEAF_begemotBridgeBaseAddress:
1152
case LEAF_begemotBridgeBaseNumPorts:
1153
case LEAF_begemotBridgeBaseType:
1154
return (SNMP_ERR_NOT_WRITEABLE);
1155
}
1156
abort();
1157
1158
case SNMP_OP_ROLLBACK:
1159
return (bridge_rollback_if_status(ctx, val, sub));
1160
1161
case SNMP_OP_COMMIT:
1162
return (bridge_commit_if_status(val, sub));
1163
}
1164
abort();
1165
1166
get:
1167
switch (val->var.subs[sub - 1]) {
1168
case LEAF_begemotBridgeBaseName:
1169
return (string_get(val, bif->bif_name, -1));
1170
1171
case LEAF_begemotBridgeBaseAddress:
1172
return (string_get(val, bif->br_addr.octet, ETHER_ADDR_LEN));
1173
1174
case LEAF_begemotBridgeBaseNumPorts:
1175
val->v.integer = bif->num_ports;
1176
return (SNMP_ERR_NOERROR);
1177
1178
case LEAF_begemotBridgeBaseType:
1179
val->v.integer = bif->br_type;
1180
return (SNMP_ERR_NOERROR);
1181
1182
case LEAF_begemotBridgeBaseStatus:
1183
val->v.integer = bif->if_status;
1184
return (SNMP_ERR_NOERROR);
1185
}
1186
1187
abort();
1188
}
1189
1190
int
1191
op_begemot_stp(struct snmp_context *ctx, struct snmp_value *val,
1192
uint sub, uint iidx __unused, enum snmp_op op)
1193
{
1194
struct bridge_if *bif;
1195
1196
if (time(NULL) - bridge_list_age > bridge_get_data_maxage())
1197
bridge_update_all_ifs();
1198
1199
switch (op) {
1200
case SNMP_OP_GET:
1201
if ((bif = bridge_if_index_get(&val->var, sub)) == NULL)
1202
return (SNMP_ERR_NOSUCHNAME);
1203
goto get;
1204
1205
case SNMP_OP_GETNEXT:
1206
if ((bif = bridge_if_index_getnext(&val->var, sub)) == NULL)
1207
return (SNMP_ERR_NOSUCHNAME);
1208
bridge_if_index_append(&val->var, sub, bif);
1209
goto get;
1210
1211
case SNMP_OP_SET:
1212
if ((bif = bridge_if_index_get(&val->var, sub)) == NULL)
1213
return (SNMP_ERR_NOSUCHNAME);
1214
1215
switch (val->var.subs[sub - 1]) {
1216
case LEAF_begemotBridgeStpPriority:
1217
if (val->v.integer > SNMP_BRIDGE_MAX_PRIORITY ||
1218
val->v.integer % 4096 != 0)
1219
return (SNMP_ERR_WRONG_VALUE);
1220
1221
ctx->scratch->int1 = bif->priority;
1222
if (bridge_set_priority(bif, val->v.integer) < 0)
1223
return (SNMP_ERR_GENERR);
1224
return (SNMP_ERR_NOERROR);
1225
1226
case LEAF_begemotBridgeStpBridgeMaxAge:
1227
if (val->v.integer < SNMP_BRIDGE_MIN_MAGE ||
1228
val->v.integer > SNMP_BRIDGE_MAX_MAGE)
1229
return (SNMP_ERR_WRONG_VALUE);
1230
1231
ctx->scratch->int1 = bif->bridge_max_age;
1232
if (bridge_set_maxage(bif, val->v.integer) < 0)
1233
return (SNMP_ERR_GENERR);
1234
return (SNMP_ERR_NOERROR);
1235
1236
case LEAF_begemotBridgeStpBridgeHelloTime:
1237
if (val->v.integer < SNMP_BRIDGE_MIN_HTIME ||
1238
val->v.integer > SNMP_BRIDGE_MAX_HTIME)
1239
return (SNMP_ERR_WRONG_VALUE);
1240
1241
ctx->scratch->int1 = bif->bridge_hello_time;
1242
if (bridge_set_hello_time(bif, val->v.integer) < 0)
1243
return (SNMP_ERR_GENERR);
1244
return (SNMP_ERR_NOERROR);
1245
1246
case LEAF_begemotBridgeStpBridgeForwardDelay:
1247
if (val->v.integer < SNMP_BRIDGE_MIN_FDELAY ||
1248
val->v.integer > SNMP_BRIDGE_MAX_FDELAY)
1249
return (SNMP_ERR_WRONG_VALUE);
1250
1251
ctx->scratch->int1 = bif->bridge_fwd_delay;
1252
if (bridge_set_forward_delay(bif, val->v.integer) < 0)
1253
return (SNMP_ERR_GENERR);
1254
return (SNMP_ERR_NOERROR);
1255
1256
case LEAF_begemotBridgeStpVersion:
1257
if (val->v.integer !=
1258
begemotBridgeStpVersion_stpCompatible &&
1259
val->v.integer != begemotBridgeStpVersion_rstp)
1260
return (SNMP_ERR_WRONG_VALUE);
1261
1262
ctx->scratch->int1 = bif->stp_version;
1263
if (bridge_set_stp_version(bif, val->v.integer) < 0)
1264
return (SNMP_ERR_GENERR);
1265
return (SNMP_ERR_NOERROR);
1266
1267
case LEAF_begemotBridgeStpTxHoldCount:
1268
if (val->v.integer < SNMP_BRIDGE_MIN_TXHC ||
1269
val->v.integer > SNMP_BRIDGE_MAX_TXHC)
1270
return (SNMP_ERR_WRONG_VALUE);
1271
1272
ctx->scratch->int1 = bif->tx_hold_count;
1273
if (bridge_set_tx_hold_count(bif, val->v.integer) < 0)
1274
return (SNMP_ERR_GENERR);
1275
return (SNMP_ERR_NOERROR);
1276
1277
case LEAF_begemotBridgeStpProtocolSpecification:
1278
case LEAF_begemotBridgeStpTimeSinceTopologyChange:
1279
case LEAF_begemotBridgeStpTopChanges:
1280
case LEAF_begemotBridgeStpDesignatedRoot:
1281
case LEAF_begemotBridgeStpRootCost:
1282
case LEAF_begemotBridgeStpRootPort:
1283
case LEAF_begemotBridgeStpMaxAge:
1284
case LEAF_begemotBridgeStpHelloTime:
1285
case LEAF_begemotBridgeStpHoldTime:
1286
case LEAF_begemotBridgeStpForwardDelay:
1287
return (SNMP_ERR_NOT_WRITEABLE);
1288
}
1289
abort();
1290
1291
case SNMP_OP_ROLLBACK:
1292
if ((bif = bridge_if_index_get(&val->var, sub)) == NULL)
1293
return (SNMP_ERR_NOSUCHNAME);
1294
1295
switch (val->var.subs[sub - 1]) {
1296
case LEAF_begemotBridgeStpPriority:
1297
bridge_set_priority(bif, ctx->scratch->int1);
1298
break;
1299
1300
case LEAF_begemotBridgeStpBridgeMaxAge:
1301
bridge_set_maxage(bif, ctx->scratch->int1);
1302
break;
1303
1304
case LEAF_begemotBridgeStpBridgeHelloTime:
1305
bridge_set_hello_time(bif, ctx->scratch->int1);
1306
break;
1307
1308
case LEAF_begemotBridgeStpBridgeForwardDelay:
1309
bridge_set_forward_delay(bif, ctx->scratch->int1);
1310
break;
1311
1312
case LEAF_begemotBridgeStpVersion:
1313
bridge_set_stp_version(bif, ctx->scratch->int1);
1314
break;
1315
1316
case LEAF_begemotBridgeStpTxHoldCount:
1317
bridge_set_tx_hold_count(bif, ctx->scratch->int1);
1318
break;
1319
}
1320
return (SNMP_ERR_NOERROR);
1321
1322
case SNMP_OP_COMMIT:
1323
return (SNMP_ERR_NOERROR);
1324
}
1325
abort();
1326
1327
get:
1328
switch (val->var.subs[sub - 1]) {
1329
case LEAF_begemotBridgeStpProtocolSpecification:
1330
val->v.integer = bif->prot_spec;
1331
return (SNMP_ERR_NOERROR);
1332
1333
case LEAF_begemotBridgeStpPriority:
1334
val->v.integer = bif->priority;
1335
return (SNMP_ERR_NOERROR);
1336
1337
case LEAF_begemotBridgeStpTimeSinceTopologyChange:
1338
if (bridge_get_time_since_tc(bif, &(val->v.uint32)) < 0)
1339
return (SNMP_ERR_GENERR);
1340
return (SNMP_ERR_NOERROR);
1341
1342
case LEAF_begemotBridgeStpTopChanges:
1343
val->v.uint32 = bif->top_changes;
1344
return (SNMP_ERR_NOERROR);
1345
1346
case LEAF_begemotBridgeStpDesignatedRoot:
1347
return (string_get(val, bif->design_root, SNMP_BRIDGE_ID_LEN));
1348
1349
case LEAF_begemotBridgeStpRootCost:
1350
val->v.integer = bif->root_cost;
1351
return (SNMP_ERR_NOERROR);
1352
1353
case LEAF_begemotBridgeStpRootPort:
1354
val->v.integer = bif->root_port;
1355
return (SNMP_ERR_NOERROR);
1356
1357
case LEAF_begemotBridgeStpMaxAge:
1358
val->v.integer = bif->max_age;
1359
return (SNMP_ERR_NOERROR);
1360
1361
case LEAF_begemotBridgeStpHelloTime:
1362
val->v.integer = bif->hello_time;
1363
return (SNMP_ERR_NOERROR);
1364
1365
case LEAF_begemotBridgeStpHoldTime:
1366
val->v.integer = bif->hold_time;
1367
return (SNMP_ERR_NOERROR);
1368
1369
case LEAF_begemotBridgeStpForwardDelay:
1370
val->v.integer = bif->fwd_delay;
1371
return (SNMP_ERR_NOERROR);
1372
1373
case LEAF_begemotBridgeStpBridgeMaxAge:
1374
val->v.integer = bif->bridge_max_age;
1375
return (SNMP_ERR_NOERROR);
1376
1377
case LEAF_begemotBridgeStpBridgeHelloTime:
1378
val->v.integer = bif->bridge_hello_time;
1379
return (SNMP_ERR_NOERROR);
1380
1381
case LEAF_begemotBridgeStpBridgeForwardDelay:
1382
val->v.integer = bif->bridge_fwd_delay;
1383
return (SNMP_ERR_NOERROR);
1384
1385
case LEAF_begemotBridgeStpVersion:
1386
val->v.integer = bif->stp_version;
1387
return (SNMP_ERR_NOERROR);
1388
1389
case LEAF_begemotBridgeStpTxHoldCount:
1390
val->v.integer = bif->tx_hold_count;
1391
return (SNMP_ERR_NOERROR);
1392
}
1393
1394
abort();
1395
}
1396
1397
int
1398
op_begemot_tp(struct snmp_context *ctx, struct snmp_value *val,
1399
uint sub, uint iidx __unused, enum snmp_op op)
1400
{
1401
struct bridge_if *bif;
1402
1403
if (time(NULL) - bridge_list_age > bridge_get_data_maxage())
1404
bridge_update_all_ifs();
1405
1406
switch (op) {
1407
case SNMP_OP_GET:
1408
if ((bif = bridge_if_index_get(&val->var, sub)) == NULL)
1409
return (SNMP_ERR_NOSUCHNAME);
1410
goto get;
1411
1412
case SNMP_OP_GETNEXT:
1413
if ((bif = bridge_if_index_getnext(&val->var, sub)) == NULL)
1414
return (SNMP_ERR_NOSUCHNAME);
1415
bridge_if_index_append(&val->var, sub, bif);
1416
goto get;
1417
1418
case SNMP_OP_SET:
1419
if ((bif = bridge_if_index_get(&val->var, sub)) == NULL)
1420
return (SNMP_ERR_NOSUCHNAME);
1421
1422
switch (val->var.subs[sub - 1]) {
1423
case LEAF_begemotBridgeTpAgingTime:
1424
if (val->v.integer < SNMP_BRIDGE_MIN_AGE_TIME ||
1425
val->v.integer > SNMP_BRIDGE_MAX_AGE_TIME)
1426
return (SNMP_ERR_WRONG_VALUE);
1427
1428
ctx->scratch->int1 = bif->age_time;
1429
if (bridge_set_aging_time(bif, val->v.integer) < 0)
1430
return (SNMP_ERR_GENERR);
1431
return (SNMP_ERR_NOERROR);
1432
1433
case LEAF_begemotBridgeTpMaxAddresses:
1434
ctx->scratch->int1 = bif->max_addrs;
1435
if (bridge_set_max_cache(bif, val->v.integer) < 0)
1436
return (SNMP_ERR_GENERR);
1437
return (SNMP_ERR_NOERROR);
1438
1439
case LEAF_begemotBridgeTpLearnedEntryDiscards:
1440
return (SNMP_ERR_NOT_WRITEABLE);
1441
}
1442
abort();
1443
1444
case SNMP_OP_ROLLBACK:
1445
if ((bif = bridge_if_index_get(&val->var, sub)) == NULL)
1446
return (SNMP_ERR_GENERR);
1447
1448
switch (val->var.subs[sub - 1]) {
1449
case LEAF_begemotBridgeTpAgingTime:
1450
bridge_set_aging_time(bif, ctx->scratch->int1);
1451
break;
1452
1453
case LEAF_begemotBridgeTpMaxAddresses:
1454
bridge_set_max_cache(bif, ctx->scratch->int1);
1455
break;
1456
}
1457
return (SNMP_ERR_NOERROR);
1458
1459
case SNMP_OP_COMMIT:
1460
return (SNMP_ERR_NOERROR);
1461
}
1462
abort();
1463
1464
get:
1465
switch (val->var.subs[sub - 1]) {
1466
case LEAF_begemotBridgeTpLearnedEntryDiscards:
1467
val->v.uint32 = bif->lrnt_drops;
1468
return (SNMP_ERR_NOERROR);
1469
1470
case LEAF_begemotBridgeTpAgingTime:
1471
val->v.integer = bif->age_time;
1472
return (SNMP_ERR_NOERROR);
1473
1474
case LEAF_begemotBridgeTpMaxAddresses:
1475
val->v.integer = bif->max_addrs;
1476
return (SNMP_ERR_NOERROR);
1477
}
1478
1479
abort();
1480
}
1481
1482