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 dump_msg(const struct sockaddr_nl
*who
, struct nlmsghdr
*n
,
37 struct ifinfomsg
*ifi
= NLMSG_DATA(n
);
38 struct rtattr
* tb
[IFLA_MAX
+1];
39 int len
= n
->nlmsg_len
;
43 if (n
->nlmsg_type
== NLMSG_DONE
)
46 len
-= NLMSG_LENGTH(sizeof(*ifi
));
50 if (ifi
->ifi_family
!= AF_BRIDGE
&& ifi
->ifi_family
!= AF_UNSPEC
)
53 if (n
->nlmsg_type
!= RTM_NEWLINK
&&
54 n
->nlmsg_type
!= RTM_DELLINK
)
57 parse_rtattr(tb
, IFLA_MAX
, IFLA_RTA(ifi
), len
);
59 /* Check if we got this from bonding */
60 if (tb
[IFLA_MASTER
] && ifi
->ifi_family
!= AF_BRIDGE
)
63 /* Check if hearing our own state changes */
64 if (n
->nlmsg_type
== RTM_NEWLINK
&& tb
[IFLA_PROTINFO
]) {
65 uint8_t state
= *(uint8_t *)RTA_DATA(tb
[IFLA_PROTINFO
]);
67 if (state
!= BR_STATE_DISABLED
)
71 if (tb
[IFLA_IFNAME
] == NULL
) {
72 fprintf(stderr
, "BUG: nil ifname\n");
76 if (n
->nlmsg_type
== RTM_DELLINK
)
77 fprintf(fp
, "Deleted ");
79 fprintf(fp
, "%d: %s ", ifi
->ifi_index
,
80 (const char*)RTA_DATA(tb
[IFLA_IFNAME
]));
82 if (tb
[IFLA_MASTER
]) {
83 master
= *(int*)RTA_DATA(tb
[IFLA_MASTER
]);
84 fprintf(fp
, "master %s ", if_indextoname(master
, b1
));
91 bridge_notify(master
, ifi
->ifi_index
,
92 (n
->nlmsg_type
== RTM_NEWLINK
),
99 static void usage(void)
101 fprintf(stderr
, "Usage: brmon\n");
105 static int matches(const char *cmd
, const char *pattern
)
107 int len
= strlen(cmd
);
108 if (len
> strlen(pattern
))
110 return memcmp(pattern
, cmd
, len
);
114 main(int argc
, char **argv
)
116 struct rtnl_handle rth
;
117 unsigned groups
= ~RTMGRP_TC
;
122 if (matches(argv
[1], "-Version") == 0) {
123 printf("brmon %s\n", SNAPSHOT
);
125 } else if (matches(argv
[1], "link") == 0) {
128 } else if (matches(argv
[1], "bridge") == 0) {
131 } else if (strcmp(argv
[1], "all") == 0) {
133 } else if (matches(argv
[1], "help") == 0) {
136 fprintf(stderr
, "Argument \"%s\" is unknown, try \"rtmon help\".\n", argv
[1]);
143 groups
|= RTMGRP_LINK
;
145 if (rtnl_open(&rth
, groups
) < 0)
148 if (rtnl_wilddump_request(&rth
, PF_BRIDGE
, RTM_GETLINK
) < 0) {
149 perror("Cannot send dump request");
153 if (rtnl_dump_filter(&rth
, dump_msg
, stdout
, NULL
, NULL
) < 0) {
154 fprintf(stderr
, "Dump terminated\n");
158 if (rtnl_listen(&rth
, dump_msg
, stdout
) < 0)
165 #include "bridge_ctl.h"
166 #include "epoll_loop.h"
168 struct rtnl_handle rth
;
169 struct epoll_event_handler br_handler
;
171 struct rtnl_handle rth_state
;
173 void br_ev_handler(uint32_t events
, struct epoll_event_handler
*h
)
175 if (rtnl_listen(&rth
, dump_msg
, stdout
) < 0) {
176 fprintf(stderr
, "Error on bridge monitoring socket\n");
181 int init_bridge_ops(void)
183 if (rtnl_open(&rth
, ~RTMGRP_TC
) < 0) {
184 fprintf(stderr
, "Couldn't open rtnl socket for monitoring\n");
188 if (rtnl_open(&rth_state
, 0) < 0) {
189 fprintf(stderr
, "Couldn't open rtnl socket for setting state\n");
193 if (rtnl_wilddump_request(&rth
, PF_BRIDGE
, RTM_GETLINK
) < 0) {
194 fprintf(stderr
, "Cannot send dump request: %m\n");
198 if (rtnl_dump_filter(&rth
, dump_msg
, stdout
, NULL
, NULL
) < 0) {
199 fprintf(stderr
, "Dump terminated\n");
203 if (fcntl(rth
.fd
, F_SETFL
, O_NONBLOCK
) < 0) {
204 fprintf(stderr
, "Error setting O_NONBLOCK: %m\n");
208 br_handler
.fd
= rth
.fd
;
209 br_handler
.arg
= NULL
;
210 br_handler
.handler
= br_ev_handler
;
212 if (add_epoll(&br_handler
) < 0)
218 /* Send message. Response is through bridge_notify */
219 void bridge_get_configuration(void)
221 if (rtnl_wilddump_request(&rth
, PF_BRIDGE
, RTM_GETLINK
) < 0) {
222 fprintf(stderr
, "Cannot send dump request: %m\n");