2 * brmon.c RTnetlink listener.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Stephen Hemminger <shemminger@osdl.org>
11 * Modified by Srinivas Aji <Aji_Srinivas@emc.com> for use
12 * in RSTP daemon. - 2006-09-01
20 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <linux/if_bridge.h>
27 #include "libnetlink.h"
29 #include "bridge_ctl.h"
31 static const char SNAPSHOT
[] = "v0.1";
33 /* RFC 2863 operational status */
38 IF_OPER_LOWERLAYERDOWN
,
47 IF_LINK_MODE_DORMANT
, /* limit upward transition to dormant */
50 static const char *port_states
[] = {
51 [BR_STATE_DISABLED
] = "disabled",
52 [BR_STATE_LISTENING
] = "listening",
53 [BR_STATE_LEARNING
] = "learning",
54 [BR_STATE_FORWARDING
] = "forwarding",
55 [BR_STATE_BLOCKING
] = "blocking",
58 static int dump_msg(const struct sockaddr_nl
*who
, struct nlmsghdr
*n
,
62 struct ifinfomsg
*ifi
= NLMSG_DATA(n
);
63 struct rtattr
*tb
[IFLA_MAX
+ 1];
64 int len
= n
->nlmsg_len
;
66 int af_family
= ifi
->ifi_family
;
68 if (n
->nlmsg_type
== NLMSG_DONE
)
71 len
-= NLMSG_LENGTH(sizeof(*ifi
));
77 if (filter
.ifindex
&& ifi
->ifi_index
!= filter
.ifindex
)
80 if (filter
.up
&& !(ifi
->ifi_flags
& IFF_UP
))
83 if (ifi
->ifi_family
!= AF_BRIDGE
&& ifi
->ifi_family
!= AF_UNSPEC
)
86 if (n
->nlmsg_type
!= RTM_NEWLINK
&& n
->nlmsg_type
!= RTM_DELLINK
)
89 parse_rtattr(tb
, IFLA_MAX
, IFLA_RTA(ifi
), len
);
91 /* Check if we got this from bonding */
92 if (tb
[IFLA_MASTER
] && af_family
!= AF_BRIDGE
)
96 if (tb
[IFLA_PRIORITY
] && af_family
== AF_BRIDGE
) {
97 bridge_bpdu_rcv(ifi
->ifi_index
,
98 RTA_DATA(tb
[IFLA_PRIORITY
]),
99 RTA_PAYLOAD(tb
[IFLA_PRIORITY
]));
103 if (tb
[IFLA_IFNAME
] == NULL
) {
104 fprintf(stderr
, "BUG: nil ifname\n");
108 if (n
->nlmsg_type
== RTM_DELLINK
)
109 fprintf(fp
, "Deleted ");
111 fprintf(fp
, "%d: %s ", ifi
->ifi_index
,
112 tb
[IFLA_IFNAME
] ? (char *)RTA_DATA(tb
[IFLA_IFNAME
]) : "<nil>");
114 if (tb
[IFLA_OPERSTATE
]) {
115 int state
= *(int *)RTA_DATA(tb
[IFLA_OPERSTATE
]);
117 case IF_OPER_UNKNOWN
:
118 fprintf(fp
, "Unknown ");
120 case IF_OPER_NOTPRESENT
:
121 fprintf(fp
, "Not Present ");
124 fprintf(fp
, "Down ");
126 case IF_OPER_LOWERLAYERDOWN
:
127 fprintf(fp
, "Lowerlayerdown ");
129 case IF_OPER_TESTING
:
130 fprintf(fp
, "Testing ");
132 case IF_OPER_DORMANT
:
133 fprintf(fp
, "Dormant ");
139 fprintf(fp
, "State(%d) ", state
);
144 fprintf(fp
, "mtu %u ", *(int *)RTA_DATA(tb
[IFLA_MTU
]));
146 if (tb
[IFLA_MASTER
]) {
147 fprintf(fp
, "master %s ",
148 if_indextoname(*(int *)RTA_DATA(tb
[IFLA_MASTER
]), b1
));
151 if (tb
[IFLA_PROTINFO
]) {
152 uint8_t state
= *(uint8_t *) RTA_DATA(tb
[IFLA_PROTINFO
]);
153 if (state
<= BR_STATE_BLOCKING
)
154 fprintf(fp
, "state %s", port_states
[state
]);
156 fprintf(fp
, "state (%d)", state
);
162 int newlink
= (n
->nlmsg_type
== RTM_NEWLINK
);
164 if (newlink
&& tb
[IFLA_OPERSTATE
]) {
165 int state
= *(int *)RTA_DATA(tb
[IFLA_OPERSTATE
]);
166 up
= (state
== IF_OPER_UP
)
167 || (state
== IF_OPER_UNKNOWN
);
170 bridge_notify((tb
[IFLA_MASTER
] ? *(int *)
171 RTA_DATA(tb
[IFLA_MASTER
]) : -1), ifi
->ifi_index
,
178 static void usage(void)
180 fprintf(stderr
, "Usage: brmon\n");
184 static int matches(const char *cmd
, const char *pattern
)
186 int len
= strlen(cmd
);
187 if (len
> strlen(pattern
))
189 return memcmp(pattern
, cmd
, len
);
192 int main(int argc
, char **argv
)
194 struct rtnl_handle rth
;
195 unsigned groups
= ~RTMGRP_TC
;
200 if (matches(argv
[1], "-Version") == 0) {
201 printf("brmon %s\n", SNAPSHOT
);
203 } else if (matches(argv
[1], "link") == 0) {
206 } else if (matches(argv
[1], "bridge") == 0) {
209 } else if (strcmp(argv
[1], "all") == 0) {
211 } else if (matches(argv
[1], "help") == 0) {
215 "Argument \"%s\" is unknown, try \"rtmon help\".\n",
224 groups
|= RTMGRP_LINK
;
226 if (rtnl_open(&rth
, groups
) < 0)
229 if (rtnl_wilddump_request(&rth
, PF_BRIDGE
, RTM_GETLINK
) < 0) {
230 perror("Cannot send dump request");
234 if (rtnl_dump_filter(&rth
, dump_msg
, stdout
, NULL
, NULL
) < 0) {
235 fprintf(stderr
, "Dump terminated\n");
239 if (rtnl_listen(&rth
, dump_msg
, stdout
) < 0)
246 #include "bridge_ctl.h"
247 #include "epoll_loop.h"
249 struct rtnl_handle rth
;
250 struct epoll_event_handler br_handler
;
252 struct rtnl_handle rth_state
;
254 void br_ev_handler(uint32_t events
, struct epoll_event_handler
*h
)
256 if (rtnl_listen(&rth
, dump_msg
, stdout
) < 0) {
257 fprintf(stderr
, "Error on bridge monitoring socket\n");
262 int init_bridge_ops(void)
264 if (rtnl_open(&rth
, ~RTMGRP_TC
) < 0) {
265 fprintf(stderr
, "Couldn't open rtnl socket for monitoring\n");
269 if (rtnl_open(&rth_state
, 0) < 0) {
271 "Couldn't open rtnl socket for setting state\n");
275 if (rtnl_wilddump_request(&rth
, PF_BRIDGE
, RTM_GETLINK
) < 0) {
276 fprintf(stderr
, "Cannot send dump request: %m\n");
280 if (rtnl_dump_filter(&rth
, dump_msg
, stdout
, NULL
, NULL
) < 0) {
281 fprintf(stderr
, "Dump terminated\n");
285 if (fcntl(rth
.fd
, F_SETFL
, O_NONBLOCK
) < 0) {
286 fprintf(stderr
, "Error setting O_NONBLOCK: %m\n");
290 br_handler
.fd
= rth
.fd
;
291 br_handler
.arg
= NULL
;
292 br_handler
.handler
= br_ev_handler
;
294 if (add_epoll(&br_handler
) < 0)
300 /* Send message. Response is through bridge_notify */
301 void bridge_get_configuration(void)
303 if (rtnl_wilddump_request(&rth
, PF_BRIDGE
, RTM_GETLINK
) < 0) {
304 fprintf(stderr
, "Cannot send dump request: %m\n");