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_sys.c
105655 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 OS specific ioctls.
30
*/
31
32
#include <sys/ioctl.h>
33
#include <sys/param.h>
34
#include <sys/module.h>
35
#include <sys/linker.h>
36
#include <sys/socket.h>
37
#include <sys/sysctl.h>
38
39
#include <net/bridgestp.h>
40
#include <net/ethernet.h>
41
#include <net/if.h>
42
#include <net/if_bridgevar.h>
43
#include <net/if_dl.h>
44
#include <net/if_mib.h>
45
#include <net/if_types.h>
46
#include <netinet/in.h>
47
48
#include <errno.h>
49
#include <ifaddrs.h>
50
#include <stdarg.h>
51
#include <stdlib.h>
52
#include <stdio.h>
53
#include <string.h>
54
#include <syslog.h>
55
56
#include <bsnmp/snmpmod.h>
57
#include <bsnmp/snmp_mibII.h>
58
59
#define SNMPTREE_TYPES
60
#include "bridge_tree.h"
61
#include "bridge_snmp.h"
62
63
int sock = -1;
64
65
int
66
bridge_ioctl_init(void)
67
{
68
if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
69
syslog(LOG_ERR, "cannot open socket : %s", strerror(errno));
70
return (-1);
71
}
72
73
return (0);
74
}
75
76
/*
77
* Load the if_bridge.ko module in kernel if not already there.
78
*/
79
int
80
bridge_kmod_load(void)
81
{
82
int fileid, modid;
83
const char mod_name[] = "if_bridge";
84
struct module_stat mstat;
85
86
/* Scan files in kernel. */
87
mstat.version = sizeof(struct module_stat);
88
for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) {
89
/* Scan modules in file. */
90
for (modid = kldfirstmod(fileid); modid > 0;
91
modid = modfnext(modid)) {
92
93
if (modstat(modid, &mstat) < 0)
94
continue;
95
96
if (strcmp(mod_name, mstat.name) == 0)
97
return (0);
98
}
99
}
100
101
/* Not present - load it. */
102
if (kldload(mod_name) < 0) {
103
syslog(LOG_ERR, "failed to load %s kernel module", mod_name);
104
return (-1);
105
}
106
107
return (1);
108
}
109
110
/************************************************************************
111
* Bridge interfaces.
112
*/
113
114
/*
115
* Convert the kernel uint64_t value for a bridge id
116
*/
117
static void
118
snmp_uint64_to_bridgeid(uint64_t id, bridge_id b_id)
119
{
120
int i;
121
u_char *o;
122
123
o = (u_char *) &id;
124
125
for (i = 0; i < SNMP_BRIDGE_ID_LEN; i++, o++)
126
b_id[SNMP_BRIDGE_ID_LEN - i - 1] = *o;
127
}
128
129
/*
130
* Fetch the bridge configuration parameters from the kernel excluding
131
* it's base MAC address.
132
*/
133
static int
134
bridge_get_conf_param(struct bridge_if *bif)
135
{
136
struct ifdrv ifd;
137
struct ifbrparam b_param;
138
139
strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ);
140
ifd.ifd_len = sizeof(b_param);
141
ifd.ifd_data = &b_param;
142
143
/* Bridge priority. */
144
ifd.ifd_cmd = BRDGGPRI;
145
if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) {
146
syslog(LOG_ERR, "update bridge: ioctl(BRDGGPRI) failed: %s",
147
strerror(errno));
148
return (-1);
149
}
150
151
bif->priority = b_param.ifbrp_prio;
152
153
/* Configured max age. */
154
ifd.ifd_cmd = BRDGGMA;
155
if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) {
156
syslog(LOG_ERR, "update bridge: ioctl(BRDGGMA) failed: %s",
157
strerror(errno));
158
return (-1);
159
}
160
161
/* Centi-seconds. */
162
bif->bridge_max_age = 100 * b_param.ifbrp_maxage;
163
164
/* Configured hello time. */
165
ifd.ifd_cmd = BRDGGHT;
166
if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) {
167
syslog(LOG_ERR, "update bridge: ioctl(BRDGGHT) failed: %s",
168
strerror(errno));
169
return (-1);
170
}
171
bif->bridge_hello_time = 100 * b_param.ifbrp_hellotime;
172
173
/* Forward delay. */
174
ifd.ifd_cmd = BRDGGFD;
175
if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) {
176
syslog(LOG_ERR, "update bridge: ioctl(BRDGGFD) failed: %s",
177
strerror(errno));
178
return (-1);
179
}
180
bif->bridge_fwd_delay = 100 * b_param.ifbrp_fwddelay;
181
182
/* Number of dropped addresses. */
183
ifd.ifd_cmd = BRDGGRTE;
184
if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) {
185
syslog(LOG_ERR, "update bridge: ioctl(BRDGGRTE) failed: %s",
186
strerror(errno));
187
return (-1);
188
}
189
bif->lrnt_drops = b_param.ifbrp_cexceeded;
190
191
/* Address table timeout. */
192
ifd.ifd_cmd = BRDGGTO;
193
if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) {
194
syslog(LOG_ERR, "update bridge: ioctl(BRDGGTO) failed: %s",
195
strerror(errno));
196
return (-1);
197
}
198
bif->age_time = b_param.ifbrp_ctime;
199
200
/* Address table size. */
201
ifd.ifd_cmd = BRDGGCACHE;
202
if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) {
203
syslog(LOG_ERR, "update bridge: ioctl(BRDGGCACHE) "
204
"failed: %s", strerror(errno));
205
return (-1);
206
}
207
bif->max_addrs = b_param.ifbrp_csize;
208
209
return (0);
210
}
211
212
/*
213
* Fetch the current bridge STP operational parameters.
214
* Returns: -1 - on error;
215
* 0 - old TC time and Root Port values are same;
216
* 1 - topologyChange notification should be sent;
217
* 2 - newRoot notification should be sent.
218
*/
219
int
220
bridge_get_op_param(struct bridge_if *bif)
221
{
222
int new_root_send;
223
struct ifdrv ifd;
224
struct ifbropreq b_req;
225
226
strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ);
227
ifd.ifd_len = sizeof(b_req);
228
ifd.ifd_data = &b_req;
229
ifd.ifd_cmd = BRDGPARAM;
230
231
if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) {
232
syslog(LOG_ERR, "update bridge: ioctl(BRDGPARAM) failed: %s",
233
strerror(errno));
234
return (-1);
235
}
236
237
bif->max_age = 100 * b_req.ifbop_maxage;
238
bif->hello_time = 100 * b_req.ifbop_hellotime;
239
bif->fwd_delay = 100 * b_req.ifbop_fwddelay;
240
bif->stp_version = b_req.ifbop_protocol;
241
bif->tx_hold_count = b_req.ifbop_holdcount;
242
243
if (b_req.ifbop_root_port == 0 &&
244
bif->root_port != b_req.ifbop_root_port)
245
new_root_send = 2;
246
else
247
new_root_send = 0;
248
249
bif->root_port = b_req.ifbop_root_port;
250
bif->root_cost = b_req.ifbop_root_path_cost;
251
snmp_uint64_to_bridgeid(b_req.ifbop_designated_root,
252
bif->design_root);
253
254
if (bif->last_tc_time.tv_sec != b_req.ifbop_last_tc_time.tv_sec) {
255
bif->top_changes++;
256
bif->last_tc_time.tv_sec = b_req.ifbop_last_tc_time.tv_sec;
257
bif->last_tc_time.tv_usec = b_req.ifbop_last_tc_time.tv_usec;
258
259
/*
260
* "The trap is not sent if a (begemotBridge)NewRoot
261
* trap is sent for the same transition."
262
*/
263
if (new_root_send == 0)
264
return (1);
265
}
266
267
return (new_root_send);
268
}
269
270
int
271
bridge_getinfo_bif(struct bridge_if *bif)
272
{
273
if (bridge_get_conf_param(bif) < 0)
274
return (-1);
275
276
return (bridge_get_op_param(bif));
277
}
278
279
int
280
bridge_set_priority(struct bridge_if *bif, int32_t priority)
281
{
282
struct ifdrv ifd;
283
struct ifbrparam b_param;
284
285
strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ);
286
ifd.ifd_len = sizeof(b_param);
287
ifd.ifd_data = &b_param;
288
b_param.ifbrp_prio = (uint32_t) priority;
289
ifd.ifd_cmd = BRDGSPRI;
290
291
if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) {
292
syslog(LOG_ERR, "set bridge param: ioctl(BRDGSPRI) "
293
"failed: %s", strerror(errno));
294
return (-1);
295
}
296
297
/*
298
* Re-fetching the data from the driver after that might be a good
299
* idea, since changing our bridge's priority should invoke
300
* recalculation of the active spanning tree topology in the network.
301
*/
302
bif->priority = priority;
303
return (0);
304
}
305
306
/*
307
* Convert 1/100 of seconds to 1/256 of seconds.
308
* Timeout ::= TEXTUAL-CONVENTION.
309
* To convert a Timeout value into a value in units of
310
* 1/256 seconds, the following algorithm should be used:
311
* b = floor( (n * 256) / 100)
312
* The conversion to 1/256 of a second happens in the kernel -
313
* just make sure we correctly convert the seconds to Timeout
314
* and vice versa.
315
*/
316
static uint32_t
317
snmp_timeout2_sec(int32_t secs)
318
{
319
return (secs / 100);
320
}
321
322
int
323
bridge_set_maxage(struct bridge_if *bif, int32_t max_age)
324
{
325
struct ifdrv ifd;
326
struct ifbrparam b_param;
327
328
strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ);
329
ifd.ifd_len = sizeof(b_param);
330
ifd.ifd_data = &b_param;
331
b_param.ifbrp_maxage = snmp_timeout2_sec(max_age);
332
ifd.ifd_cmd = BRDGSMA;
333
334
if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) {
335
syslog(LOG_ERR, "set bridge param: ioctl(BRDGSMA) "
336
"failed: %s", strerror(errno));
337
return (-1);
338
}
339
340
bif->bridge_max_age = max_age;
341
return (0);
342
}
343
344
int
345
bridge_set_hello_time(struct bridge_if *bif, int32_t hello_time)
346
{
347
struct ifdrv ifd;
348
struct ifbrparam b_param;
349
350
strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ);
351
ifd.ifd_len = sizeof(b_param);
352
ifd.ifd_data = &b_param;
353
b_param.ifbrp_hellotime = snmp_timeout2_sec(hello_time);
354
ifd.ifd_cmd = BRDGSHT;
355
356
if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) {
357
syslog(LOG_ERR, "set bridge param: ioctl(BRDGSHT) "
358
"failed: %s", strerror(errno));
359
return (-1);
360
}
361
362
bif->bridge_hello_time = b_param.ifbrp_hellotime;
363
return (0);
364
}
365
366
int
367
bridge_set_forward_delay(struct bridge_if *bif, int32_t fwd_delay)
368
{
369
struct ifdrv ifd;
370
struct ifbrparam b_param;
371
372
strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ);
373
ifd.ifd_len = sizeof(b_param);
374
ifd.ifd_data = &b_param;
375
b_param.ifbrp_fwddelay = snmp_timeout2_sec(fwd_delay);
376
ifd.ifd_cmd = BRDGSFD;
377
378
if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) {
379
syslog(LOG_ERR, "set bridge param: ioctl(BRDGSFD) "
380
"failed: %s", strerror(errno));
381
return (-1);
382
}
383
384
bif->bridge_fwd_delay = b_param.ifbrp_fwddelay;
385
return (0);
386
}
387
388
int
389
bridge_set_aging_time(struct bridge_if *bif, int32_t age_time)
390
{
391
struct ifdrv ifd;
392
struct ifbrparam b_param;
393
394
strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ);
395
ifd.ifd_len = sizeof(b_param);
396
ifd.ifd_data = &b_param;
397
b_param.ifbrp_ctime = (uint32_t) age_time;
398
ifd.ifd_cmd = BRDGSTO;
399
400
if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) {
401
syslog(LOG_ERR, "set bridge param: ioctl(BRDGSTO) "
402
"failed: %s", strerror(errno));
403
return (-1);
404
}
405
406
bif->age_time = age_time;
407
return (0);
408
}
409
410
int
411
bridge_set_max_cache(struct bridge_if *bif, int32_t max_cache)
412
{
413
struct ifdrv ifd;
414
struct ifbrparam b_param;
415
416
strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ);
417
ifd.ifd_len = sizeof(b_param);
418
ifd.ifd_data = &b_param;
419
b_param.ifbrp_csize = max_cache;
420
ifd.ifd_cmd = BRDGSCACHE;
421
422
if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) {
423
syslog(LOG_ERR, "set bridge param: ioctl(BRDGSCACHE) "
424
"failed: %s", strerror(errno));
425
return (-1);
426
}
427
428
bif->max_addrs = b_param.ifbrp_csize;
429
return (0);
430
}
431
432
int
433
bridge_set_tx_hold_count(struct bridge_if *bif, int32_t tx_hc)
434
{
435
struct ifdrv ifd;
436
struct ifbrparam b_param;
437
438
if (tx_hc < SNMP_BRIDGE_MIN_TXHC || tx_hc > SNMP_BRIDGE_MAX_TXHC)
439
return (-1);
440
441
strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ);
442
ifd.ifd_len = sizeof(b_param);
443
ifd.ifd_data = &b_param;
444
b_param.ifbrp_txhc = tx_hc;
445
ifd.ifd_cmd = BRDGSTXHC;
446
447
if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) {
448
syslog(LOG_ERR, "set bridge param: ioctl(BRDGSTXHC) "
449
"failed: %s", strerror(errno));
450
return (-1);
451
}
452
453
bif->tx_hold_count = b_param.ifbrp_txhc;
454
return (0);
455
}
456
457
int
458
bridge_set_stp_version(struct bridge_if *bif, int32_t stp_proto)
459
{
460
struct ifdrv ifd;
461
struct ifbrparam b_param;
462
463
strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ);
464
ifd.ifd_len = sizeof(b_param);
465
ifd.ifd_data = &b_param;
466
b_param.ifbrp_proto = stp_proto;
467
ifd.ifd_cmd = BRDGSPROTO;
468
469
if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) {
470
syslog(LOG_ERR, "set bridge param: ioctl(BRDGSPROTO) "
471
"failed: %s", strerror(errno));
472
return (-1);
473
}
474
475
bif->stp_version = b_param.ifbrp_proto;
476
return (0);
477
}
478
479
/*
480
* Set the bridge interface status to up/down.
481
*/
482
int
483
bridge_set_if_up(const char* b_name, int8_t up)
484
{
485
int flags;
486
struct ifreq ifr;
487
488
bzero(&ifr, sizeof(ifr));
489
strlcpy(ifr.ifr_name, b_name, sizeof(ifr.ifr_name));
490
if (ioctl(sock, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
491
syslog(LOG_ERR, "set bridge up: ioctl(SIOCGIFFLAGS) "
492
"failed: %s", strerror(errno));
493
return (-1);
494
}
495
496
flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16);
497
if (up == 1)
498
flags |= IFF_UP;
499
else
500
flags &= ~IFF_UP;
501
502
ifr.ifr_flags = flags & 0xffff;
503
ifr.ifr_flagshigh = flags >> 16;
504
if (ioctl(sock, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
505
syslog(LOG_ERR, "set bridge up: ioctl(SIOCSIFFLAGS) "
506
"failed: %s", strerror(errno));
507
return (-1);
508
}
509
510
return (0);
511
}
512
513
int
514
bridge_create(const char *b_name)
515
{
516
char *new_name;
517
struct ifreq ifr;
518
519
bzero(&ifr, sizeof(ifr));
520
strlcpy(ifr.ifr_name, b_name, sizeof(ifr.ifr_name));
521
522
if (ioctl(sock, SIOCIFCREATE, &ifr) < 0) {
523
syslog(LOG_ERR, "create bridge: ioctl(SIOCIFCREATE) "
524
"failed: %s", strerror(errno));
525
return (-1);
526
}
527
528
if (strcmp(b_name, ifr.ifr_name) == 0)
529
return (0);
530
531
if ((new_name = strdup(b_name)) == NULL) {
532
syslog(LOG_ERR, "create bridge: strdup() failed");
533
return (-1);
534
}
535
536
ifr.ifr_data = new_name;
537
if (ioctl(sock, SIOCSIFNAME, (caddr_t) &ifr) < 0) {
538
syslog(LOG_ERR, "create bridge: ioctl(SIOCSIFNAME) "
539
"failed: %s", strerror(errno));
540
free(new_name);
541
return (-1);
542
}
543
544
return (0);
545
}
546
547
int
548
bridge_destroy(const char *b_name)
549
{
550
struct ifreq ifr;
551
552
bzero(&ifr, sizeof(ifr));
553
strlcpy(ifr.ifr_name, b_name, sizeof(ifr.ifr_name));
554
555
if (ioctl(sock, SIOCIFDESTROY, &ifr) < 0) {
556
syslog(LOG_ERR, "destroy bridge: ioctl(SIOCIFDESTROY) "
557
"failed: %s", strerror(errno));
558
return (-1);
559
}
560
561
return (0);
562
}
563
564
/*
565
* Fetch the bridge base MAC address. Return pointer to the
566
* buffer containing the MAC address, NULL on failure.
567
*/
568
u_char *
569
bridge_get_basemac(const char *bif_name, u_char *mac, size_t mlen)
570
{
571
int len;
572
char if_name[IFNAMSIZ];
573
struct ifaddrs *ifap, *ifa;
574
struct sockaddr_dl sdl;
575
576
if (getifaddrs(&ifap) != 0) {
577
syslog(LOG_ERR, "bridge get mac: getifaddrs() failed - %s",
578
strerror(errno));
579
return (NULL);
580
}
581
582
for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
583
if (ifa->ifa_addr->sa_family != AF_LINK)
584
continue;
585
586
/*
587
* Not just casting because of alignment constraints.
588
*/
589
bcopy(ifa->ifa_addr, &sdl, sizeof(struct sockaddr_dl));
590
591
if (sdl.sdl_alen > mlen)
592
continue;
593
594
if ((len = sdl.sdl_nlen) >= IFNAMSIZ)
595
len = IFNAMSIZ - 1;
596
597
bcopy(sdl.sdl_data, if_name, len);
598
if_name[len] = '\0';
599
600
if (strcmp(bif_name, if_name) == 0) {
601
bcopy(sdl.sdl_data + sdl.sdl_nlen, mac, sdl.sdl_alen);
602
freeifaddrs(ifap);
603
return (mac);
604
}
605
}
606
607
freeifaddrs(ifap);
608
return (NULL);
609
}
610
611
/************************************************************************
612
* Bridge ports.
613
*/
614
615
/*
616
* Convert the kernel STP port state into
617
* the corresopnding enumerated type from SNMP Bridge MIB.
618
*/
619
static int
620
state2snmp_st(uint8_t ifbr_state)
621
{
622
switch (ifbr_state) {
623
case BSTP_IFSTATE_DISABLED:
624
return (StpPortState_disabled);
625
case BSTP_IFSTATE_LISTENING:
626
return (StpPortState_listening);
627
case BSTP_IFSTATE_LEARNING:
628
return (StpPortState_learning);
629
case BSTP_IFSTATE_FORWARDING:
630
return (StpPortState_forwarding);
631
case BSTP_IFSTATE_BLOCKING:
632
case BSTP_IFSTATE_DISCARDING:
633
return (StpPortState_blocking);
634
}
635
636
return (StpPortState_broken);
637
}
638
639
/*
640
* Fill in a bridge member information according to data polled from kernel.
641
*/
642
static void
643
bridge_port_getinfo_conf(struct ifbreq *k_info, struct bridge_port *bp)
644
{
645
bp->state = state2snmp_st(k_info->ifbr_state);
646
bp->priority = k_info->ifbr_priority;
647
648
/*
649
* RFC 4188:
650
* "New implementations should support dot1dStpPortPathCost32.
651
* If the port path costs exceeds the maximum value of this
652
* object then this object should report the maximum value,
653
* namely 65535. Applications should try to read the
654
* dot1dStpPortPathCost32 object if this object reports
655
* the maximum value."
656
*/
657
658
if (k_info->ifbr_ifsflags & IFBIF_BSTP_ADMCOST)
659
bp->admin_path_cost = k_info->ifbr_path_cost;
660
else
661
bp->admin_path_cost = 0;
662
663
bp->path_cost = k_info->ifbr_path_cost;
664
665
if (k_info->ifbr_ifsflags & IFBIF_STP)
666
bp->enable = dot1dStpPortEnable_enabled;
667
else
668
bp->enable = dot1dStpPortEnable_disabled;
669
670
/* Begemot Bridge MIB only. */
671
if (k_info->ifbr_ifsflags & IFBIF_SPAN)
672
bp->span_enable = begemotBridgeBaseSpanEnabled_enabled;
673
else
674
bp->span_enable = begemotBridgeBaseSpanEnabled_disabled;
675
676
if (k_info->ifbr_ifsflags & IFBIF_PRIVATE)
677
bp->priv_set = TruthValue_true;
678
else
679
bp->priv_set = TruthValue_false;
680
681
if (k_info->ifbr_ifsflags & IFBIF_BSTP_ADMEDGE)
682
bp->admin_edge = TruthValue_true;
683
else
684
bp->admin_edge = TruthValue_false;
685
686
if (k_info->ifbr_ifsflags & IFBIF_BSTP_EDGE)
687
bp->oper_edge = TruthValue_true;
688
else
689
bp->oper_edge = TruthValue_false;
690
691
if (k_info->ifbr_ifsflags & IFBIF_BSTP_AUTOPTP) {
692
bp->admin_ptp = StpPortAdminPointToPointType_auto;
693
if (k_info->ifbr_ifsflags & IFBIF_BSTP_PTP)
694
bp->oper_ptp = TruthValue_true;
695
else
696
bp->oper_ptp = TruthValue_false;
697
} else if (k_info->ifbr_ifsflags & IFBIF_BSTP_PTP) {
698
bp->admin_ptp = StpPortAdminPointToPointType_forceTrue;
699
bp->oper_ptp = TruthValue_true;
700
} else {
701
bp->admin_ptp = StpPortAdminPointToPointType_forceFalse;
702
bp->oper_ptp = TruthValue_false;
703
}
704
}
705
706
/*
707
* Fill in a bridge interface STP information according to
708
* data polled from kernel.
709
*/
710
static void
711
bridge_port_getinfo_opstp(struct ifbpstpreq *bp_stp, struct bridge_port *bp)
712
{
713
bp->enable = dot1dStpPortEnable_enabled;
714
bp->fwd_trans = bp_stp->ifbp_fwd_trans;
715
bp->design_cost = bp_stp->ifbp_design_cost;
716
snmp_uint64_to_bridgeid(bp_stp->ifbp_design_root, bp->design_root);
717
snmp_uint64_to_bridgeid(bp_stp->ifbp_design_bridge, bp->design_bridge);
718
bcopy(&(bp_stp->ifbp_design_port), &(bp->design_port),
719
sizeof(uint16_t));
720
}
721
722
/*
723
* Clear a bridge interface STP information.
724
*/
725
static void
726
bridge_port_clearinfo_opstp(struct bridge_port *bp)
727
{
728
if (bp->enable == dot1dStpPortEnable_enabled) {
729
bp->design_cost = 0;
730
bzero(&(bp->design_root), sizeof(bridge_id));
731
bzero(&(bp->design_bridge), sizeof(bridge_id));
732
bzero(&(bp->design_port), sizeof(port_id));
733
bp->fwd_trans = 0;
734
}
735
736
bp->enable = dot1dStpPortEnable_disabled;
737
}
738
739
/*
740
* Set a bridge member priority.
741
*/
742
int
743
bridge_port_set_priority(const char *bif_name, struct bridge_port *bp,
744
int32_t priority)
745
{
746
struct ifdrv ifd;
747
struct ifbreq b_req;
748
749
strlcpy(ifd.ifd_name, bif_name, sizeof(ifd.ifd_name));
750
ifd.ifd_len = sizeof(b_req);
751
ifd.ifd_data = &b_req;
752
strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname));
753
754
b_req.ifbr_priority = (uint8_t) priority;
755
ifd.ifd_cmd = BRDGSIFPRIO;
756
757
if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) {
758
syslog(LOG_ERR, "set member %s param: ioctl(BRDGSIFPRIO) "
759
"failed: %s", bp->p_name, strerror(errno));
760
return (-1);
761
}
762
763
bp->priority = priority;
764
return (0);
765
}
766
767
/*
768
* Set a bridge member STP-enabled flag.
769
*/
770
int
771
bridge_port_set_stp_enable(const char *bif_name, struct bridge_port *bp,
772
uint32_t enable)
773
{
774
struct ifdrv ifd;
775
struct ifbreq b_req;
776
777
if (bp->enable == enable)
778
return (0);
779
780
bzero(&b_req, sizeof(b_req));
781
strlcpy(ifd.ifd_name, bif_name, sizeof(ifd.ifd_name));
782
ifd.ifd_len = sizeof(b_req);
783
ifd.ifd_data = &b_req;
784
strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname));
785
ifd.ifd_cmd = BRDGGIFFLGS;
786
787
if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) {
788
syslog(LOG_ERR, "get member %s param: ioctl(BRDGGIFFLGS) "
789
"failed: %s", bp->p_name, strerror(errno));
790
return (-1);
791
}
792
793
if (enable == dot1dStpPortEnable_enabled)
794
b_req.ifbr_ifsflags |= IFBIF_STP;
795
else
796
b_req.ifbr_ifsflags &= ~IFBIF_STP;
797
798
ifd.ifd_cmd = BRDGSIFFLGS;
799
if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) {
800
syslog(LOG_ERR, "set member %s param: ioctl(BRDGSIFFLGS) "
801
"failed: %s", bp->p_name, strerror(errno));
802
return (-1);
803
}
804
805
bp->enable = enable;
806
return (0);
807
}
808
809
/*
810
* Set a bridge member STP path cost.
811
*/
812
int
813
bridge_port_set_path_cost(const char *bif_name, struct bridge_port *bp,
814
int32_t path_cost)
815
{
816
struct ifdrv ifd;
817
struct ifbreq b_req;
818
819
if (path_cost < SNMP_PORT_MIN_PATHCOST ||
820
path_cost > SNMP_PORT_PATHCOST_OBSOLETE)
821
return (-2);
822
823
strlcpy(ifd.ifd_name, bif_name, sizeof(ifd.ifd_name));
824
ifd.ifd_len = sizeof(b_req);
825
ifd.ifd_data = &b_req;
826
strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname));
827
828
b_req.ifbr_path_cost = path_cost;
829
ifd.ifd_cmd = BRDGSIFCOST;
830
831
if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) {
832
syslog(LOG_ERR, "set member %s param: ioctl(BRDGSIFCOST) "
833
"failed: %s", bp->p_name, strerror(errno));
834
return (-1);
835
}
836
837
bp->admin_path_cost = path_cost;
838
839
return (0);
840
}
841
842
/*
843
* Set the PonitToPoint status of the link administratively.
844
*/
845
int
846
bridge_port_set_admin_ptp(const char *bif_name, struct bridge_port *bp,
847
uint32_t admin_ptp)
848
{
849
struct ifdrv ifd;
850
struct ifbreq b_req;
851
852
if (bp->admin_ptp == admin_ptp)
853
return (0);
854
855
bzero(&b_req, sizeof(b_req));
856
strlcpy(ifd.ifd_name, bif_name, sizeof(ifd.ifd_name));
857
ifd.ifd_len = sizeof(b_req);
858
ifd.ifd_data = &b_req;
859
strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname));
860
ifd.ifd_cmd = BRDGGIFFLGS;
861
862
if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) {
863
syslog(LOG_ERR, "get member %s param: ioctl(BRDGGIFFLGS) "
864
"failed: %s", bp->p_name, strerror(errno));
865
return (-1);
866
}
867
868
switch (admin_ptp) {
869
case StpPortAdminPointToPointType_forceTrue:
870
b_req.ifbr_ifsflags &= ~IFBIF_BSTP_AUTOPTP;
871
b_req.ifbr_ifsflags |= IFBIF_BSTP_PTP;
872
break;
873
case StpPortAdminPointToPointType_forceFalse:
874
b_req.ifbr_ifsflags &= ~IFBIF_BSTP_AUTOPTP;
875
b_req.ifbr_ifsflags &= ~IFBIF_BSTP_PTP;
876
break;
877
case StpPortAdminPointToPointType_auto:
878
b_req.ifbr_ifsflags |= IFBIF_BSTP_AUTOPTP;
879
break;
880
}
881
882
ifd.ifd_cmd = BRDGSIFFLGS;
883
if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) {
884
syslog(LOG_ERR, "set member %s param: ioctl(BRDGSIFFLGS) "
885
"failed: %s", bp->p_name, strerror(errno));
886
return (-1);
887
}
888
889
bp->admin_ptp = admin_ptp;
890
return (0);
891
}
892
893
/*
894
* Set admin edge.
895
*/
896
int
897
bridge_port_set_admin_edge(const char *bif_name, struct bridge_port *bp,
898
uint32_t enable)
899
{
900
struct ifdrv ifd;
901
struct ifbreq b_req;
902
903
if (bp->admin_edge == enable)
904
return (0);
905
906
bzero(&b_req, sizeof(b_req));
907
strlcpy(ifd.ifd_name, bif_name, sizeof(ifd.ifd_name));
908
ifd.ifd_len = sizeof(b_req);
909
ifd.ifd_data = &b_req;
910
strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname));
911
ifd.ifd_cmd = BRDGGIFFLGS;
912
913
if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) {
914
syslog(LOG_ERR, "get member %s param: ioctl(BRDGGIFFLGS) "
915
"failed: %s", bp->p_name, strerror(errno));
916
return (-1);
917
}
918
919
if (enable == TruthValue_true) {
920
b_req.ifbr_ifsflags &= ~IFBIF_BSTP_AUTOEDGE;
921
b_req.ifbr_ifsflags |= IFBIF_BSTP_EDGE;
922
} else
923
b_req.ifbr_ifsflags &= ~IFBIF_BSTP_EDGE;
924
925
ifd.ifd_cmd = BRDGSIFFLGS;
926
if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) {
927
syslog(LOG_ERR, "set member %s param: ioctl(BRDGSIFFLGS) "
928
"failed: %s", bp->p_name, strerror(errno));
929
return (-1);
930
}
931
932
bp->admin_edge = enable;
933
934
return (0);
935
}
936
937
/*
938
* Set 'private' flag.
939
*/
940
int
941
bridge_port_set_private(const char *bif_name, struct bridge_port *bp,
942
uint32_t priv_set)
943
{
944
struct ifdrv ifd;
945
struct ifbreq b_req;
946
947
if (bp->priv_set == priv_set)
948
return (0);
949
950
bzero(&b_req, sizeof(b_req));
951
strlcpy(ifd.ifd_name, bif_name, sizeof(ifd.ifd_name));
952
ifd.ifd_len = sizeof(b_req);
953
ifd.ifd_data = &b_req;
954
strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname));
955
ifd.ifd_cmd = BRDGGIFFLGS;
956
957
if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) {
958
syslog(LOG_ERR, "get member %s param: ioctl(BRDGGIFFLGS) "
959
"failed: %s", bp->p_name, strerror(errno));
960
return (-1);
961
}
962
963
if (priv_set == TruthValue_true)
964
b_req.ifbr_ifsflags |= IFBIF_PRIVATE;
965
else if (priv_set == TruthValue_false)
966
b_req.ifbr_ifsflags &= ~IFBIF_PRIVATE;
967
else
968
return (SNMP_ERR_WRONG_VALUE);
969
970
ifd.ifd_cmd = BRDGSIFFLGS;
971
if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) {
972
syslog(LOG_ERR, "set member %s param: ioctl(BRDGSIFFLGS) "
973
"failed: %s", bp->p_name, strerror(errno));
974
return (-1);
975
}
976
977
bp->priv_set = priv_set;
978
979
return (0);
980
}
981
982
983
/*
984
* Add a bridge member port.
985
*/
986
int
987
bridge_port_addm(struct bridge_port *bp, const char *b_name)
988
{
989
struct ifdrv ifd;
990
struct ifbreq b_req;
991
992
bzero(&ifd, sizeof(ifd));
993
bzero(&b_req, sizeof(b_req));
994
995
strlcpy(ifd.ifd_name, b_name, sizeof(ifd.ifd_name));
996
ifd.ifd_len = sizeof(b_req);
997
ifd.ifd_data = &b_req;
998
strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname));
999
1000
if (bp->span_enable == begemotBridgeBaseSpanEnabled_enabled)
1001
ifd.ifd_cmd = BRDGADDS;
1002
else
1003
ifd.ifd_cmd = BRDGADD;
1004
1005
if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) {
1006
syslog(LOG_ERR, "%s - add member : ioctl(%s) failed: %s",
1007
bp->p_name,
1008
(ifd.ifd_cmd == BRDGADDS ? "BRDGADDS" : "BRDGADD"),
1009
strerror(errno));
1010
return (-1);
1011
}
1012
1013
return (0);
1014
}
1015
1016
/*
1017
* Delete a bridge member port.
1018
*/
1019
int
1020
bridge_port_delm(struct bridge_port *bp, const char *b_name)
1021
{
1022
struct ifdrv ifd;
1023
struct ifbreq b_req;
1024
1025
bzero(&ifd, sizeof(ifd));
1026
bzero(&b_req, sizeof(b_req));
1027
1028
strlcpy(ifd.ifd_name, b_name, sizeof(ifd.ifd_name));
1029
ifd.ifd_len = sizeof(b_req);
1030
ifd.ifd_data = &b_req;
1031
strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname));
1032
1033
if (bp->span_enable == begemotBridgeBaseSpanEnabled_enabled)
1034
ifd.ifd_cmd = BRDGDELS;
1035
else
1036
ifd.ifd_cmd = BRDGDEL;
1037
1038
if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) {
1039
syslog(LOG_ERR, "%s - add member : ioctl(%s) failed: %s",
1040
bp->p_name,
1041
(ifd.ifd_cmd == BRDGDELS ? "BRDGDELS" : "BRDGDEL"),
1042
strerror(errno));
1043
return (-1);
1044
}
1045
1046
return (0);
1047
}
1048
1049
/*
1050
* Fetch the bridge member list from kernel.
1051
* Return -1 on error, or buffer len if successful.
1052
*/
1053
static int32_t
1054
bridge_port_get_iflist(struct bridge_if *bif, struct ifbreq **buf)
1055
{
1056
int n = 128;
1057
uint32_t len;
1058
struct ifbreq *ninbuf;
1059
struct ifbifconf ifbc;
1060
struct ifdrv ifd;
1061
1062
*buf = NULL;
1063
strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ);
1064
ifd.ifd_cmd = BRDGGIFS;
1065
ifd.ifd_len = sizeof(ifbc);
1066
ifd.ifd_data = &ifbc;
1067
1068
for ( ; ; ) {
1069
len = n * sizeof(struct ifbreq);
1070
if ((ninbuf = (struct ifbreq *)realloc(*buf, len)) == NULL) {
1071
syslog(LOG_ERR, "get bridge member list: "
1072
"realloc failed: %s", strerror(errno));
1073
free(*buf);
1074
*buf = NULL;
1075
return (-1);
1076
}
1077
1078
ifbc.ifbic_len = len;
1079
ifbc.ifbic_req = *buf = ninbuf;
1080
1081
if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) {
1082
syslog(LOG_ERR, "get bridge member list: ioctl "
1083
"(BRDGGIFS) failed: %s", strerror(errno));
1084
free(*buf);
1085
buf = NULL;
1086
return (-1);
1087
}
1088
1089
if ((ifbc.ifbic_len + sizeof(struct ifbreq)) < len)
1090
break;
1091
1092
n += 64;
1093
}
1094
1095
return (ifbc.ifbic_len);
1096
}
1097
1098
/*
1099
* Fetch the bridge STP member list from kernel.
1100
* Return -1 on error, or buffer len if successful.
1101
*/
1102
static int32_t
1103
bridge_port_get_ifstplist(struct bridge_if *bif, struct ifbpstpreq **buf)
1104
{
1105
int n = 128;
1106
uint32_t len;
1107
struct ifbpstpreq *ninbuf;
1108
struct ifbpstpconf ifbstp;
1109
struct ifdrv ifd;
1110
1111
*buf = NULL;
1112
strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ);
1113
ifd.ifd_cmd = BRDGGIFSSTP;
1114
ifd.ifd_len = sizeof(ifbstp);
1115
ifd.ifd_data = &ifbstp;
1116
1117
for ( ; ; ) {
1118
len = n * sizeof(struct ifbpstpreq);
1119
if ((ninbuf = (struct ifbpstpreq *)
1120
realloc(*buf, len)) == NULL) {
1121
syslog(LOG_ERR, "get bridge STP ports list: "
1122
"realloc failed: %s", strerror(errno));
1123
free(*buf);
1124
*buf = NULL;
1125
return (-1);
1126
}
1127
1128
ifbstp.ifbpstp_len = len;
1129
ifbstp.ifbpstp_req = *buf = ninbuf;
1130
1131
if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) {
1132
syslog(LOG_ERR, "get bridge STP ports list: ioctl "
1133
"(BRDGGIFSSTP) failed: %s", strerror(errno));
1134
free(*buf);
1135
buf = NULL;
1136
return (-1);
1137
}
1138
1139
if ((ifbstp.ifbpstp_len + sizeof(struct ifbpstpreq)) < len)
1140
break;
1141
1142
n += 64;
1143
}
1144
1145
return (ifbstp.ifbpstp_len);
1146
}
1147
1148
/*
1149
* Locate a bridge if STP params structure in a buffer.
1150
*/
1151
static struct ifbpstpreq *
1152
bridge_port_find_ifstplist(uint8_t port_no, struct ifbpstpreq *buf,
1153
uint32_t buf_len)
1154
{
1155
uint32_t i;
1156
struct ifbpstpreq *bstp;
1157
1158
for (i = 0; i < buf_len / sizeof(struct ifbpstpreq); i++) {
1159
bstp = buf + i;
1160
if (bstp->ifbp_portno == port_no)
1161
return (bstp);
1162
}
1163
1164
return (NULL);
1165
}
1166
1167
/*
1168
* Read the initial info for all members of a bridge interface.
1169
* Returns the number of ports, 0 - if none, otherwise
1170
* -1 if some other error occurred.
1171
*/
1172
int
1173
bridge_getinfo_bif_ports(struct bridge_if *bif)
1174
{
1175
uint32_t i;
1176
int32_t buf_len;
1177
struct ifbreq *b_req_buf, *b_req;
1178
struct ifbpstpreq *bs_req_buf, *bs_req;
1179
struct bridge_port *bp;
1180
struct mibif *m_if;
1181
1182
if ((buf_len = bridge_port_get_iflist(bif, &b_req_buf)) < 0)
1183
return (-1);
1184
1185
for (i = 0; i < buf_len / sizeof(struct ifbreq); i++) {
1186
b_req = b_req_buf + i;
1187
1188
if ((m_if = mib_find_if_sys(b_req->ifbr_portno)) != NULL) {
1189
/* Hopefully we will not fail here. */
1190
if ((bp = bridge_new_port(m_if, bif)) != NULL) {
1191
bp->status = RowStatus_active;
1192
bridge_port_getinfo_conf(b_req, bp);
1193
bridge_port_getinfo_mibif(m_if, bp);
1194
}
1195
} else {
1196
syslog(LOG_ERR, "bridge member %s not present "
1197
"in mibII ifTable", b_req->ifbr_ifsname);
1198
}
1199
}
1200
free(b_req_buf);
1201
1202
if ((buf_len = bridge_port_get_ifstplist(bif, &bs_req_buf)) < 0)
1203
return (-1);
1204
1205
for (bp = bridge_port_bif_first(bif); bp != NULL;
1206
bp = bridge_port_bif_next(bp)) {
1207
if ((bs_req = bridge_port_find_ifstplist(bp->port_no,
1208
bs_req_buf, buf_len)) == NULL)
1209
bridge_port_clearinfo_opstp(bp);
1210
else
1211
bridge_port_getinfo_opstp(bs_req, bp);
1212
}
1213
free(bs_req_buf);
1214
1215
return (i);
1216
}
1217
1218
/*
1219
* Update the information for the bridge interface members.
1220
*/
1221
int
1222
bridge_update_memif(struct bridge_if *bif)
1223
{
1224
int updated;
1225
uint32_t i;
1226
int32_t buf_len;
1227
struct ifbreq *b_req_buf, *b_req;
1228
struct ifbpstpreq *bs_req_buf, *bs_req;
1229
struct bridge_port *bp, *bp_next;
1230
struct mibif *m_if;
1231
1232
if ((buf_len = bridge_port_get_iflist(bif, &b_req_buf)) < 0)
1233
return (-1);
1234
1235
updated = 0;
1236
1237
#define BP_FOUND 0x01
1238
for (i = 0; i < buf_len / sizeof(struct ifbreq); i++) {
1239
b_req = b_req_buf + i;
1240
1241
if ((m_if = mib_find_if_sys(b_req->ifbr_portno)) == NULL) {
1242
syslog(LOG_ERR, "bridge member %s not present "
1243
"in mibII ifTable", b_req->ifbr_ifsname);
1244
continue;
1245
}
1246
1247
if ((bp = bridge_port_find(m_if->index, bif)) == NULL &&
1248
(bp = bridge_new_port(m_if, bif)) != NULL) {
1249
bp->status = RowStatus_active;
1250
}
1251
1252
if (bp != NULL) {
1253
updated++;
1254
bridge_port_getinfo_conf(b_req, bp);
1255
bridge_port_getinfo_mibif(m_if, bp);
1256
bp->flags |= BP_FOUND;
1257
}
1258
}
1259
free(b_req_buf);
1260
1261
/* Clean up list. */
1262
for (bp = bridge_port_bif_first(bif); bp != NULL; bp = bp_next) {
1263
bp_next = bridge_port_bif_next(bp);
1264
1265
if ((bp->flags & BP_FOUND) == 0 &&
1266
bp->status == RowStatus_active)
1267
bridge_port_remove(bp, bif);
1268
else
1269
bp->flags |= ~BP_FOUND;
1270
}
1271
#undef BP_FOUND
1272
1273
if ((buf_len = bridge_port_get_ifstplist(bif, &bs_req_buf)) < 0)
1274
return (-1);
1275
1276
for (bp = bridge_port_bif_first(bif); bp != NULL;
1277
bp = bridge_port_bif_next(bp)) {
1278
if ((bs_req = bridge_port_find_ifstplist(bp->port_no,
1279
bs_req_buf, buf_len)) == NULL)
1280
bridge_port_clearinfo_opstp(bp);
1281
else
1282
bridge_port_getinfo_opstp(bs_req, bp);
1283
}
1284
free(bs_req_buf);
1285
bif->ports_age = time(NULL);
1286
1287
return (updated);
1288
}
1289
1290
/************************************************************************
1291
* Bridge addresses.
1292
*/
1293
1294
/*
1295
* Update the bridge address info according to the polled data.
1296
*/
1297
static void
1298
bridge_addrs_info_ifaddrlist(struct ifbareq *ifba, struct tp_entry *tpe)
1299
{
1300
tpe->port_no = if_nametoindex(ifba->ifba_ifsname);
1301
1302
if ((ifba->ifba_flags & IFBAF_TYPEMASK) == IFBAF_STATIC)
1303
tpe->status = TpFdbStatus_mgmt;
1304
else
1305
tpe->status = TpFdbStatus_learned;
1306
}
1307
1308
/*
1309
* Read the bridge addresses from kernel.
1310
* Return -1 on error, or buffer len if successful.
1311
*/
1312
static int32_t
1313
bridge_addrs_getinfo_ifalist(struct bridge_if *bif, struct ifbareq **buf)
1314
{
1315
int n = 128;
1316
uint32_t len;
1317
struct ifbareq *ninbuf;
1318
struct ifbaconf bac;
1319
struct ifdrv ifd;
1320
1321
*buf = NULL;
1322
strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ);
1323
ifd.ifd_cmd = BRDGRTS;
1324
ifd.ifd_len = sizeof(bac);
1325
ifd.ifd_data = &bac;
1326
1327
for ( ; ; ) {
1328
len = n * sizeof(struct ifbareq);
1329
if ((ninbuf = (struct ifbareq *)realloc(*buf, len)) == NULL) {
1330
syslog(LOG_ERR, "get bridge address list: "
1331
" realloc failed: %s", strerror(errno));
1332
free(*buf);
1333
*buf = NULL;
1334
return (-1);
1335
}
1336
1337
bac.ifbac_len = len;
1338
bac.ifbac_req = *buf = ninbuf;
1339
1340
if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) {
1341
syslog(LOG_ERR, "get bridge address list: "
1342
"ioctl(BRDGRTS) failed: %s", strerror(errno));
1343
free(*buf);
1344
buf = NULL;
1345
return (-1);
1346
}
1347
1348
if ((bac.ifbac_len + sizeof(struct ifbareq)) < len)
1349
break;
1350
1351
n += 64;
1352
}
1353
1354
return (bac.ifbac_len);
1355
}
1356
1357
/*
1358
* Read the initial info for all addresses on a bridge interface.
1359
* Returns the number of addresses, 0 - if none, otherwise
1360
* -1 if some other error occurred.
1361
*/
1362
int
1363
bridge_getinfo_bif_addrs(struct bridge_if *bif)
1364
{
1365
uint32_t i;
1366
int32_t buf_len;
1367
struct ifbareq *addr_req_buf, *addr_req;
1368
struct tp_entry *te;
1369
1370
if ((buf_len = bridge_addrs_getinfo_ifalist(bif, &addr_req_buf)) < 0)
1371
return (-1);
1372
1373
for (i = 0; i < buf_len / sizeof(struct ifbareq); i++) {
1374
addr_req = addr_req_buf + i;
1375
1376
if ((te = bridge_new_addrs(addr_req->ifba_dst, bif)) != NULL)
1377
bridge_addrs_info_ifaddrlist(addr_req, te);
1378
}
1379
1380
free(addr_req_buf);
1381
return (i);
1382
}
1383
1384
/*
1385
* Update the addresses for the bridge interface.
1386
*/
1387
int
1388
bridge_update_addrs(struct bridge_if *bif)
1389
{
1390
int added, updated;
1391
uint32_t i;
1392
int32_t buf_len;
1393
struct tp_entry *te, *te_next;
1394
struct ifbareq *addr_req_buf, *addr_req;
1395
1396
if ((buf_len = bridge_addrs_getinfo_ifalist(bif, &addr_req_buf)) < 0)
1397
return (-1);
1398
1399
added = updated = 0;
1400
1401
#define BA_FOUND 0x01
1402
for (i = 0; i < buf_len / sizeof(struct ifbareq); i++) {
1403
addr_req = addr_req_buf + i;
1404
1405
if ((te = bridge_addrs_find(addr_req->ifba_dst, bif)) == NULL) {
1406
added++;
1407
1408
if ((te = bridge_new_addrs(addr_req->ifba_dst, bif))
1409
== NULL)
1410
continue;
1411
} else
1412
updated++;
1413
1414
bridge_addrs_info_ifaddrlist(addr_req, te);
1415
te-> flags |= BA_FOUND;
1416
}
1417
free(addr_req_buf);
1418
1419
for (te = bridge_addrs_bif_first(bif); te != NULL; te = te_next) {
1420
te_next = bridge_addrs_bif_next(te);
1421
1422
if ((te-> flags & BA_FOUND) == 0)
1423
bridge_addrs_remove(te, bif);
1424
else
1425
te-> flags &= ~BA_FOUND;
1426
}
1427
#undef BA_FOUND
1428
1429
bif->addrs_age = time(NULL);
1430
return (updated + added);
1431
}
1432
1433
/************************************************************************
1434
* Bridge packet filtering.
1435
*/
1436
const char bridge_sysctl[] = "net.link.bridge.";
1437
1438
static struct {
1439
int32_t val;
1440
const char *name;
1441
} bridge_pf_sysctl[] = {
1442
{ 1, "pfil_bridge" },
1443
{ 1, "pfil_member" },
1444
{ 1, "pfil_onlyip" },
1445
{ 0, "ipfw" },
1446
};
1447
1448
int32_t
1449
bridge_get_pfval(uint8_t which)
1450
{
1451
1452
if (which > nitems(bridge_pf_sysctl) || which < 1)
1453
return (-1);
1454
1455
return (bridge_pf_sysctl[which - 1].val);
1456
}
1457
1458
int32_t
1459
bridge_do_pfctl(int32_t bridge_ctl, enum snmp_op op, int32_t *val)
1460
{
1461
char *mib_oid;
1462
size_t len, s_len;
1463
int32_t i, s_i;
1464
1465
if (bridge_ctl >= LEAF_begemotBridgeLayer2PfStatus)
1466
return (-2);
1467
1468
if (op == SNMP_OP_SET) {
1469
s_i = *val;
1470
s_len = sizeof(s_i);
1471
} else
1472
s_len = 0;
1473
1474
len = sizeof(i);
1475
1476
asprintf(&mib_oid, "%s%s", bridge_sysctl,
1477
bridge_pf_sysctl[bridge_ctl].name);
1478
if (mib_oid == NULL)
1479
return (-1);
1480
1481
if (sysctlbyname(mib_oid, &i, &len, (op == SNMP_OP_SET ? &s_i : NULL),
1482
s_len) == -1) {
1483
syslog(LOG_ERR, "sysctl(%s) failed - %s", mib_oid,
1484
strerror(errno));
1485
free(mib_oid);
1486
return (-1);
1487
}
1488
1489
bridge_pf_sysctl[bridge_ctl].val = i;
1490
*val = i;
1491
1492
free(mib_oid);
1493
1494
return (i);
1495
}
1496
1497
void
1498
bridge_pf_dump(void)
1499
{
1500
uint8_t i;
1501
1502
for (i = 0; i < nitems(bridge_pf_sysctl); i++) {
1503
syslog(LOG_ERR, "%s%s = %d", bridge_sysctl,
1504
bridge_pf_sysctl[i].name, bridge_pf_sysctl[i].val);
1505
}
1506
}
1507
1508