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 static int is_up(const struct ifinfomsg
*ifi
)
35 return (ifi
->ifi_flags
& IFF_UP
) && (ifi
->ifi_flags
& IFF_RUNNING
);
38 static int dump_msg(const struct sockaddr_nl
*who
, struct nlmsghdr
*n
,
42 struct ifinfomsg
*ifi
= NLMSG_DATA(n
);
43 struct rtattr
* tb
[IFLA_MAX
+1];
44 int len
= n
->nlmsg_len
;
48 if (n
->nlmsg_type
== NLMSG_DONE
)
51 len
-= NLMSG_LENGTH(sizeof(*ifi
));
55 if (ifi
->ifi_family
!= AF_BRIDGE
&& ifi
->ifi_family
!= AF_UNSPEC
)
58 if (n
->nlmsg_type
!= RTM_NEWLINK
&&
59 n
->nlmsg_type
!= RTM_DELLINK
)
62 parse_rtattr(tb
, IFLA_MAX
, IFLA_RTA(ifi
), len
);
64 /* Check if we got this from bonding */
65 if (tb
[IFLA_MASTER
] && ifi
->ifi_family
!= AF_BRIDGE
)
68 /* Check if hearing our own state changes */
69 if (n
->nlmsg_type
== RTM_NEWLINK
&& tb
[IFLA_PROTINFO
]) {
70 uint8_t state
= *(uint8_t *)RTA_DATA(tb
[IFLA_PROTINFO
]);
72 if (state
!= BR_STATE_DISABLED
)
76 if (tb
[IFLA_IFNAME
] == NULL
) {
77 fprintf(stderr
, "BUG: nil ifname\n");
81 if (n
->nlmsg_type
== RTM_DELLINK
)
82 fprintf(fp
, "Deleted ");
84 fprintf(fp
, "%d: %s ", ifi
->ifi_index
,
85 (const char*)RTA_DATA(tb
[IFLA_IFNAME
]));
87 if (tb
[IFLA_MASTER
]) {
88 master
= *(int*)RTA_DATA(tb
[IFLA_MASTER
]);
89 fprintf(fp
, "master %s ", if_indextoname(master
, b1
));
96 bridge_notify(master
, ifi
->ifi_index
,
97 (n
->nlmsg_type
== RTM_NEWLINK
),
104 static void usage(void)
106 fprintf(stderr
, "Usage: brmon\n");
110 static int matches(const char *cmd
, const char *pattern
)
112 int len
= strlen(cmd
);
113 if (len
> strlen(pattern
))
115 return memcmp(pattern
, cmd
, len
);
119 main(int argc
, char **argv
)
121 struct rtnl_handle rth
;
122 unsigned groups
= ~RTMGRP_TC
;
127 if (matches(argv
[1], "-Version") == 0) {
128 printf("brmon %s\n", SNAPSHOT
);
130 } else if (matches(argv
[1], "link") == 0) {
133 } else if (matches(argv
[1], "bridge") == 0) {
136 } else if (strcmp(argv
[1], "all") == 0) {
138 } else if (matches(argv
[1], "help") == 0) {
141 fprintf(stderr
, "Argument \"%s\" is unknown, try \"rtmon help\".\n", argv
[1]);
148 groups
|= RTMGRP_LINK
;
150 if (rtnl_open(&rth
, groups
) < 0)
153 if (rtnl_wilddump_request(&rth
, PF_BRIDGE
, RTM_GETLINK
) < 0) {
154 perror("Cannot send dump request");
158 if (rtnl_dump_filter(&rth
, dump_msg
, stdout
, NULL
, NULL
) < 0) {
159 fprintf(stderr
, "Dump terminated\n");
163 if (rtnl_listen(&rth
, dump_msg
, stdout
) < 0)
170 #include "bridge_ctl.h"
171 #include "epoll_loop.h"
173 struct rtnl_handle rth
;
174 struct epoll_event_handler br_handler
;
176 struct rtnl_handle rth_state
;
178 void br_ev_handler(uint32_t events
, struct epoll_event_handler
*h
)
180 if (rtnl_listen(&rth
, dump_msg
, stdout
) < 0) {
181 fprintf(stderr
, "Error on bridge monitoring socket\n");
186 int init_bridge_ops(void)
188 if (rtnl_open(&rth
, ~RTMGRP_TC
) < 0) {
189 fprintf(stderr
, "Couldn't open rtnl socket for monitoring\n");
193 if (rtnl_open(&rth_state
, 0) < 0) {
194 fprintf(stderr
, "Couldn't open rtnl socket for setting state\n");
198 if (rtnl_wilddump_request(&rth
, PF_BRIDGE
, RTM_GETLINK
) < 0) {
199 fprintf(stderr
, "Cannot send dump request: %m\n");
203 if (rtnl_dump_filter(&rth
, dump_msg
, stdout
, NULL
, NULL
) < 0) {
204 fprintf(stderr
, "Dump terminated\n");
208 if (fcntl(rth
.fd
, F_SETFL
, O_NONBLOCK
) < 0) {
209 fprintf(stderr
, "Error setting O_NONBLOCK: %m\n");
213 br_handler
.fd
= rth
.fd
;
214 br_handler
.arg
= NULL
;
215 br_handler
.handler
= br_ev_handler
;
217 if (add_epoll(&br_handler
) < 0)
223 /* Send message. Response is through bridge_notify */
224 void bridge_get_configuration(void)
226 if (rtnl_wilddump_request(&rth
, PF_BRIDGE
, RTM_GETLINK
) < 0) {
227 fprintf(stderr
, "Cannot send dump request: %m\n");