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>
10 * Modified by Srinivas Aji <Aji_Srinivas@emc.com>
11 * for use in RSTP daemon. - 2006-09-01
12 * Modified by Vitalii Demianets <vitas@nppfactor.kiev.ua>
13 * for use in MSTP daemon. - 2011-07-18
19 #include <netinet/in.h>
20 #include <linux/if_bridge.h>
22 #include "libnetlink.h"
23 #include "bridge_ctl.h"
24 #include "netif_utils.h"
25 #include "epoll_loop.h"
27 /* RFC 2863 operational status */
33 IF_OPER_LOWERLAYERDOWN
,
43 IF_LINK_MODE_DORMANT
, /* limit upward transition to dormant */
46 static const char *port_states
[] =
48 [BR_STATE_DISABLED
] = "disabled",
49 [BR_STATE_LISTENING
] = "listening",
50 [BR_STATE_LEARNING
] = "learning",
51 [BR_STATE_FORWARDING
] = "forwarding",
52 [BR_STATE_BLOCKING
] = "blocking",
55 static struct rtnl_handle rth
;
56 static struct epoll_event_handler br_handler
;
58 struct rtnl_handle rth_state
;
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
;
72 if(n
->nlmsg_type
== NLMSG_DONE
)
75 len
-= NLMSG_LENGTH(sizeof(*ifi
));
81 if(af_family
!= AF_BRIDGE
&& af_family
!= AF_UNSPEC
)
84 if(n
->nlmsg_type
!= RTM_NEWLINK
&& n
->nlmsg_type
!= RTM_DELLINK
)
87 parse_rtattr(tb
, IFLA_MAX
, IFLA_RTA(ifi
), len
);
89 /* Check if we got this from bonding */
90 if(tb
[IFLA_MASTER
] && af_family
!= AF_BRIDGE
)
93 if(tb
[IFLA_IFNAME
] == NULL
)
95 fprintf(stderr
, "BUG: nil ifname\n");
99 if(n
->nlmsg_type
== RTM_DELLINK
)
100 fprintf(fp
, "Deleted ");
102 fprintf(fp
, "%d: %s ", ifi
->ifi_index
, (char*)RTA_DATA(tb
[IFLA_IFNAME
]));
104 if(tb
[IFLA_OPERSTATE
])
106 int state
= *(int*)RTA_DATA(tb
[IFLA_OPERSTATE
]);
109 case IF_OPER_UNKNOWN
:
110 fprintf(fp
, "Unknown ");
112 case IF_OPER_NOTPRESENT
:
113 fprintf(fp
, "Not Present ");
116 fprintf(fp
, "Down ");
118 case IF_OPER_LOWERLAYERDOWN
:
119 fprintf(fp
, "Lowerlayerdown ");
121 case IF_OPER_TESTING
:
122 fprintf(fp
, "Testing ");
124 case IF_OPER_DORMANT
:
125 fprintf(fp
, "Dormant ");
131 fprintf(fp
, "State(%d) ", state
);
136 fprintf(fp
, "mtu %u ", *(int*)RTA_DATA(tb
[IFLA_MTU
]));
140 fprintf(fp
, "master %s ",
141 if_indextoname(*(int*)RTA_DATA(tb
[IFLA_MASTER
]), b1
));
144 if(tb
[IFLA_PROTINFO
])
146 uint8_t state
= *(uint8_t *)RTA_DATA(tb
[IFLA_PROTINFO
]);
147 if(state
<= BR_STATE_BLOCKING
)
148 fprintf(fp
, "state %s", port_states
[state
]);
150 fprintf(fp
, "state (%d)", state
);
156 newlink
= (n
->nlmsg_type
== RTM_NEWLINK
);
158 if(newlink
&& tb
[IFLA_OPERSTATE
])
160 int state
= *(uint8_t*)RTA_DATA(tb
[IFLA_OPERSTATE
]);
161 up
= (state
== IF_OPER_UP
) || (state
== IF_OPER_UNKNOWN
);
165 br_index
= *(int*)RTA_DATA(tb
[IFLA_MASTER
]);
166 else if(is_bridge((char*)RTA_DATA(tb
[IFLA_IFNAME
])))
167 br_index
= ifi
->ifi_index
;
171 bridge_notify(br_index
, ifi
->ifi_index
, newlink
, up
);
176 static inline void br_ev_handler(uint32_t events
, struct epoll_event_handler
*h
)
178 if(rtnl_listen(&rth
, dump_msg
, stdout
) < 0)
180 fprintf(stderr
, "Error on bridge monitoring socket\n");
185 int init_bridge_ops(void)
187 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)
195 fprintf(stderr
, "Couldn't open rtnl socket for setting state\n");
199 if(rtnl_wilddump_request(&rth
, PF_BRIDGE
, RTM_GETLINK
) < 0)
201 fprintf(stderr
, "Cannot send dump request: %m\n");
205 if(rtnl_dump_filter(&rth
, dump_msg
, stdout
, NULL
, NULL
) < 0)
207 fprintf(stderr
, "Dump terminated\n");
211 if(fcntl(rth
.fd
, F_SETFL
, O_NONBLOCK
) < 0)
213 fprintf(stderr
, "Error setting O_NONBLOCK: %m\n");
217 br_handler
.fd
= rth
.fd
;
218 br_handler
.arg
= NULL
;
219 br_handler
.handler
= br_ev_handler
;
221 if(add_epoll(&br_handler
) < 0)