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
)
99 if (tb
[IFLA_IFNAME
] == NULL
) {
100 fprintf(stderr
, "BUG: nil ifname\n");
104 if (n
->nlmsg_type
== RTM_DELLINK
)
105 fprintf(fp
, "Deleted ");
107 fprintf(fp
, "%d: %s ", ifi
->ifi_index
,
108 tb
[IFLA_IFNAME
] ? (char*)RTA_DATA(tb
[IFLA_IFNAME
]) : "<nil>");
111 if (tb
[IFLA_OPERSTATE
]) {
112 int state
= *(int*)RTA_DATA(tb
[IFLA_OPERSTATE
]);
114 case IF_OPER_UNKNOWN
:
115 fprintf(fp
, "Unknown "); break;
116 case IF_OPER_NOTPRESENT
:
117 fprintf(fp
, "Not Present "); break;
119 fprintf(fp
, "Down "); break;
120 case IF_OPER_LOWERLAYERDOWN
:
121 fprintf(fp
, "Lowerlayerdown "); break;
122 case IF_OPER_TESTING
:
123 fprintf(fp
, "Testing "); break;
124 case IF_OPER_DORMANT
:
125 fprintf(fp
, "Dormant "); break;
127 fprintf(fp
, "Up "); break;
129 fprintf(fp
, "State(%d) ", state
);
134 fprintf(fp
, "mtu %u ", *(int*)RTA_DATA(tb
[IFLA_MTU
]));
136 if (tb
[IFLA_MASTER
]) {
137 fprintf(fp
, "master %s ",
138 if_indextoname(*(int*)RTA_DATA(tb
[IFLA_MASTER
]), b1
));
141 if (tb
[IFLA_PROTINFO
]) {
142 uint8_t state
= *(uint8_t *)RTA_DATA(tb
[IFLA_PROTINFO
]);
143 if (state
<= BR_STATE_BLOCKING
)
144 fprintf(fp
, "state %s", port_states
[state
]);
146 fprintf(fp
, "state (%d)", state
);
153 int newlink
= (n
->nlmsg_type
== RTM_NEWLINK
);
155 if (newlink
&& tb
[IFLA_OPERSTATE
]) {
156 int state
= *(int*)RTA_DATA(tb
[IFLA_OPERSTATE
]);
157 up
= (state
== IF_OPER_UP
) || (state
== IF_OPER_UNKNOWN
);
160 bridge_notify((tb
[IFLA_MASTER
]?*(int*)RTA_DATA(tb
[IFLA_MASTER
]):-1),
161 ifi
->ifi_index
, newlink
, up
);
167 static void usage(void)
169 fprintf(stderr
, "Usage: brmon\n");
173 static int matches(const char *cmd
, const char *pattern
)
175 int len
= strlen(cmd
);
176 if (len
> strlen(pattern
))
178 return memcmp(pattern
, cmd
, len
);
182 main(int argc
, char **argv
)
184 struct rtnl_handle rth
;
185 unsigned groups
= ~RTMGRP_TC
;
190 if (matches(argv
[1], "-Version") == 0) {
191 printf("brmon %s\n", SNAPSHOT
);
193 } else if (matches(argv
[1], "link") == 0) {
196 } else if (matches(argv
[1], "bridge") == 0) {
199 } else if (strcmp(argv
[1], "all") == 0) {
201 } else if (matches(argv
[1], "help") == 0) {
204 fprintf(stderr
, "Argument \"%s\" is unknown, try \"rtmon help\".\n", argv
[1]);
211 groups
|= RTMGRP_LINK
;
213 if (rtnl_open(&rth
, groups
) < 0)
216 if (rtnl_wilddump_request(&rth
, PF_BRIDGE
, RTM_GETLINK
) < 0) {
217 perror("Cannot send dump request");
221 if (rtnl_dump_filter(&rth
, dump_msg
, stdout
, NULL
, NULL
) < 0) {
222 fprintf(stderr
, "Dump terminated\n");
226 if (rtnl_listen(&rth
, dump_msg
, stdout
) < 0)
233 #include "bridge_ctl.h"
234 #include "epoll_loop.h"
236 struct rtnl_handle rth
;
237 struct epoll_event_handler br_handler
;
239 struct rtnl_handle rth_state
;
241 void br_ev_handler(uint32_t events
, struct epoll_event_handler
*h
)
243 if (rtnl_listen(&rth
, dump_msg
, stdout
) < 0) {
244 fprintf(stderr
, "Error on bridge monitoring socket\n");
249 int init_bridge_ops(void)
251 if (rtnl_open(&rth
, ~RTMGRP_TC
) < 0) {
252 fprintf(stderr
, "Couldn't open rtnl socket for monitoring\n");
256 if (rtnl_open(&rth_state
, 0) < 0) {
257 fprintf(stderr
, "Couldn't open rtnl socket for setting state\n");
261 if (rtnl_wilddump_request(&rth
, PF_BRIDGE
, RTM_GETLINK
) < 0) {
262 fprintf(stderr
, "Cannot send dump request: %m\n");
266 if (rtnl_dump_filter(&rth
, dump_msg
, stdout
, NULL
, NULL
) < 0) {
267 fprintf(stderr
, "Dump terminated\n");
271 if (fcntl(rth
.fd
, F_SETFL
, O_NONBLOCK
) < 0) {
272 fprintf(stderr
, "Error setting O_NONBLOCK: %m\n");
276 br_handler
.fd
= rth
.fd
;
277 br_handler
.arg
= NULL
;
278 br_handler
.handler
= br_ev_handler
;
280 if (add_epoll(&br_handler
) < 0)
286 /* Send message. Response is through bridge_notify */
287 void bridge_get_configuration(void)
289 if (rtnl_wilddump_request(&rth
, PF_BRIDGE
, RTM_GETLINK
) < 0) {
290 fprintf(stderr
, "Cannot send dump request: %m\n");