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";
34 /* RFC 2863 operational status */
39 IF_OPER_LOWERLAYERDOWN
,
48 IF_LINK_MODE_DORMANT
, /* limit upward transition to dormant */
51 static const char *port_states
[] = {
52 [BR_STATE_DISABLED
] = "disabled",
53 [BR_STATE_LISTENING
] = "listening",
54 [BR_STATE_LEARNING
] = "learning",
55 [BR_STATE_FORWARDING
] = "forwarding",
56 [BR_STATE_BLOCKING
] = "blocking",
60 static int dump_msg(const struct sockaddr_nl
*who
, struct nlmsghdr
*n
,
64 struct ifinfomsg
*ifi
= NLMSG_DATA(n
);
65 struct rtattr
* tb
[IFLA_MAX
+1];
66 int len
= n
->nlmsg_len
;
68 int af_family
= ifi
->ifi_family
;
70 if (n
->nlmsg_type
== NLMSG_DONE
)
73 len
-= NLMSG_LENGTH(sizeof(*ifi
));
80 if (filter
.ifindex
&& ifi
->ifi_index
!= filter
.ifindex
)
83 if (filter
.up
&& !(ifi
->ifi_flags
&IFF_UP
))
86 if (ifi
->ifi_family
!= AF_BRIDGE
&& ifi
->ifi_family
!= AF_UNSPEC
)
89 if (n
->nlmsg_type
!= RTM_NEWLINK
&&
90 n
->nlmsg_type
!= RTM_DELLINK
)
93 parse_rtattr(tb
, IFLA_MAX
, IFLA_RTA(ifi
), len
);
95 /* Check if we got this from bonding */
96 if (tb
[IFLA_MASTER
] && af_family
!= AF_BRIDGE
)
100 if (tb
[IFLA_PRIORITY
] && af_family
== AF_BRIDGE
) {
101 bridge_bpdu_rcv(ifi
->ifi_index
,
102 RTA_DATA(tb
[IFLA_PRIORITY
]),
103 RTA_PAYLOAD(tb
[IFLA_PRIORITY
]));
107 if (tb
[IFLA_IFNAME
] == NULL
) {
108 fprintf(stderr
, "BUG: nil ifname\n");
112 if (n
->nlmsg_type
== RTM_DELLINK
)
113 fprintf(fp
, "Deleted ");
115 fprintf(fp
, "%d: %s ", ifi
->ifi_index
,
116 tb
[IFLA_IFNAME
] ? (char*)RTA_DATA(tb
[IFLA_IFNAME
]) : "<nil>");
119 if (tb
[IFLA_OPERSTATE
]) {
120 int state
= *(int*)RTA_DATA(tb
[IFLA_OPERSTATE
]);
122 case IF_OPER_UNKNOWN
:
123 fprintf(fp
, "Unknown "); break;
124 case IF_OPER_NOTPRESENT
:
125 fprintf(fp
, "Not Present "); break;
127 fprintf(fp
, "Down "); break;
128 case IF_OPER_LOWERLAYERDOWN
:
129 fprintf(fp
, "Lowerlayerdown "); break;
130 case IF_OPER_TESTING
:
131 fprintf(fp
, "Testing "); break;
132 case IF_OPER_DORMANT
:
133 fprintf(fp
, "Dormant "); break;
135 fprintf(fp
, "Up "); break;
137 fprintf(fp
, "State(%d) ", state
);
142 fprintf(fp
, "mtu %u ", *(int*)RTA_DATA(tb
[IFLA_MTU
]));
144 if (tb
[IFLA_MASTER
]) {
145 fprintf(fp
, "master %s ",
146 if_indextoname(*(int*)RTA_DATA(tb
[IFLA_MASTER
]), b1
));
149 if (tb
[IFLA_PROTINFO
]) {
150 uint8_t state
= *(uint8_t *)RTA_DATA(tb
[IFLA_PROTINFO
]);
151 if (state
<= BR_STATE_BLOCKING
)
152 fprintf(fp
, "state %s", port_states
[state
]);
154 fprintf(fp
, "state (%d)", state
);
161 int newlink
= (n
->nlmsg_type
== RTM_NEWLINK
);
163 if (newlink
&& tb
[IFLA_OPERSTATE
]) {
164 int state
= *(int*)RTA_DATA(tb
[IFLA_OPERSTATE
]);
165 up
= (state
== IF_OPER_UP
) || (state
== IF_OPER_UNKNOWN
);
168 bridge_notify((tb
[IFLA_MASTER
]?*(int*)RTA_DATA(tb
[IFLA_MASTER
]):-1),
169 ifi
->ifi_index
, newlink
, up
);
175 static void usage(void)
177 fprintf(stderr
, "Usage: brmon\n");
181 static int matches(const char *cmd
, const char *pattern
)
183 int len
= strlen(cmd
);
184 if (len
> strlen(pattern
))
186 return memcmp(pattern
, cmd
, len
);
190 main(int argc
, char **argv
)
192 struct rtnl_handle rth
;
193 unsigned groups
= ~RTMGRP_TC
;
198 if (matches(argv
[1], "-Version") == 0) {
199 printf("brmon %s\n", SNAPSHOT
);
201 } else if (matches(argv
[1], "link") == 0) {
204 } else if (matches(argv
[1], "bridge") == 0) {
207 } else if (strcmp(argv
[1], "all") == 0) {
209 } else if (matches(argv
[1], "help") == 0) {
212 fprintf(stderr
, "Argument \"%s\" is unknown, try \"rtmon help\".\n", argv
[1]);
219 groups
|= RTMGRP_LINK
;
221 if (rtnl_open(&rth
, groups
) < 0)
224 if (rtnl_wilddump_request(&rth
, PF_BRIDGE
, RTM_GETLINK
) < 0) {
225 perror("Cannot send dump request");
229 if (rtnl_dump_filter(&rth
, dump_msg
, stdout
, NULL
, NULL
) < 0) {
230 fprintf(stderr
, "Dump terminated\n");
234 if (rtnl_listen(&rth
, dump_msg
, stdout
) < 0)
241 #include "bridge_ctl.h"
242 #include "epoll_loop.h"
244 struct rtnl_handle rth
;
245 struct epoll_event_handler br_handler
;
247 struct rtnl_handle rth_state
;
249 void br_ev_handler(uint32_t events
, struct epoll_event_handler
*h
)
251 if (rtnl_listen(&rth
, dump_msg
, stdout
) < 0) {
252 fprintf(stderr
, "Error on bridge monitoring socket\n");
257 int init_bridge_ops(void)
259 if (rtnl_open(&rth
, ~RTMGRP_TC
) < 0) {
260 fprintf(stderr
, "Couldn't open rtnl socket for monitoring\n");
264 if (rtnl_open(&rth_state
, 0) < 0) {
265 fprintf(stderr
, "Couldn't open rtnl socket for setting state\n");
269 if (rtnl_wilddump_request(&rth
, PF_BRIDGE
, RTM_GETLINK
) < 0) {
270 fprintf(stderr
, "Cannot send dump request: %m\n");
274 if (rtnl_dump_filter(&rth
, dump_msg
, stdout
, NULL
, NULL
) < 0) {
275 fprintf(stderr
, "Dump terminated\n");
279 if (fcntl(rth
.fd
, F_SETFL
, O_NONBLOCK
) < 0) {
280 fprintf(stderr
, "Error setting O_NONBLOCK: %m\n");
284 br_handler
.fd
= rth
.fd
;
285 br_handler
.arg
= NULL
;
286 br_handler
.handler
= br_ev_handler
;
288 if (add_epoll(&br_handler
) < 0)
294 /* Send message. Response is through bridge_notify */
295 void bridge_get_configuration(void)
297 if (rtnl_wilddump_request(&rth
, PF_BRIDGE
, RTM_GETLINK
) < 0) {
298 fprintf(stderr
, "Cannot send dump request: %m\n");