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 <dvitasgs@gmail.com>
13 * for use in MSTP daemon. - 2011-07-18
19 #include <netinet/in.h>
20 #include <linux/if_bridge.h>
21 #include <libubox/uloop.h>
24 #include "libnetlink.h"
25 #include "bridge_ctl.h"
26 #include "netif_utils.h"
29 /* RFC 2863 operational status */
35 IF_OPER_LOWERLAYERDOWN
,
45 IF_LINK_MODE_DORMANT
, /* limit upward transition to dormant */
48 static const char *port_states
[] =
50 [BR_STATE_DISABLED
] = "disabled",
51 [BR_STATE_LISTENING
] = "listening",
52 [BR_STATE_LEARNING
] = "learning",
53 [BR_STATE_FORWARDING
] = "forwarding",
54 [BR_STATE_BLOCKING
] = "blocking",
57 static struct rtnl_handle rth
;
58 static struct uloop_fd ufd
;
60 struct rtnl_handle rth_state
;
62 static int dump_msg(const struct sockaddr_nl
*who
, struct nlmsghdr
*n
,
65 struct ifinfomsg
*ifi
= NLMSG_DATA(n
);
66 struct rtattr
* tb
[IFLA_MAX
+ 1];
67 int len
= n
->nlmsg_len
;
73 if(n
->nlmsg_type
== NLMSG_DONE
)
76 len
-= NLMSG_LENGTH(sizeof(*ifi
));
82 af_family
= ifi
->ifi_family
;
84 if(af_family
!= AF_BRIDGE
&& af_family
!= AF_UNSPEC
)
87 if(n
->nlmsg_type
!= RTM_NEWLINK
&& n
->nlmsg_type
!= RTM_DELLINK
)
90 parse_rtattr(tb
, IFLA_MAX
, IFLA_RTA(ifi
), len
);
92 /* Check if we got this from bonding */
93 if(tb
[IFLA_MASTER
] && af_family
!= AF_BRIDGE
)
96 if(tb
[IFLA_IFNAME
] == NULL
)
98 ERROR("BUG: nil ifname\n");
102 if(n
->nlmsg_type
== RTM_DELLINK
)
105 LOG("%d: %s ", ifi
->ifi_index
, (char*)RTA_DATA(tb
[IFLA_IFNAME
]));
107 if(tb
[IFLA_OPERSTATE
])
109 __u8 state
= *(__u8
*)RTA_DATA(tb
[IFLA_OPERSTATE
]);
112 case IF_OPER_UNKNOWN
:
115 case IF_OPER_NOTPRESENT
:
121 case IF_OPER_LOWERLAYERDOWN
:
122 LOG("Lowerlayerdown ");
124 case IF_OPER_TESTING
:
127 case IF_OPER_DORMANT
:
134 LOG("State(%d) ", state
);
139 LOG("mtu %u ", *(int*)RTA_DATA(tb
[IFLA_MTU
]));
144 if_indextoname(*(int*)RTA_DATA(tb
[IFLA_MASTER
]), b1
));
147 if(tb
[IFLA_PROTINFO
])
149 uint8_t state
= *(uint8_t *)RTA_DATA(tb
[IFLA_PROTINFO
]);
150 if(state
<= BR_STATE_BLOCKING
)
151 LOG("state %s", port_states
[state
]);
153 LOG("state (%d)", state
);
156 newlink
= (n
->nlmsg_type
== RTM_NEWLINK
);
159 br_index
= *(int*)RTA_DATA(tb
[IFLA_MASTER
]);
160 else if(is_bridge((char*)RTA_DATA(tb
[IFLA_IFNAME
])))
161 br_index
= ifi
->ifi_index
;
165 bridge_notify(br_index
, ifi
->ifi_index
, newlink
, ifi
->ifi_flags
);
170 void bridge_event_handler(void)
172 if(rtnl_listen(&rth
, dump_msg
, stdout
) < 0)
174 ERROR("Error on bridge monitoring socket\n");
178 static void bridge_event_cb(struct uloop_fd
*fd
, unsigned int events
)
180 struct worker_event ev
= {
181 .type
= WORKER_EV_BRIDGE_EVENT
184 worker_queue_event(&ev
);
187 int init_bridge_ops(void)
189 if(rtnl_open(&rth
, RTMGRP_LINK
) < 0)
191 ERROR("Couldn't open rtnl socket for monitoring\n");
195 if(rtnl_open(&rth_state
, 0) < 0)
197 ERROR("Couldn't open rtnl socket for setting state\n");
201 if(rtnl_wilddump_request(&rth
, PF_BRIDGE
, RTM_GETLINK
) < 0)
203 ERROR("Cannot send dump request: %m\n");
207 if(rtnl_dump_filter(&rth
, dump_msg
, stdout
, NULL
, NULL
) < 0)
209 ERROR("Dump terminated\n");
213 if(fcntl(rth
.fd
, F_SETFL
, O_NONBLOCK
) < 0)
215 ERROR("Error setting O_NONBLOCK: %m\n");
220 ufd
.cb
= bridge_event_cb
;
221 uloop_fd_add(&ufd
, ULOOP_READ
| ULOOP_EDGE_TRIGGER
);
222 bridge_event_cb(&ufd
, 0);