1 /* 2 * brmon.c RTnetlink listener. 3 * 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. 8 * 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 14 */ 15 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <fcntl.h> 19 #include <netinet/in.h> 20 #include <linux/if_bridge.h> 21 #include <libubox/uloop.h> 22 23 #include "log.h" 24 #include "libnetlink.h" 25 #include "bridge_ctl.h" 26 #include "netif_utils.h" 27 #include "worker.h" 28 29 /* RFC 2863 operational status */ 30 enum 31 { 32 IF_OPER_UNKNOWN, 33 IF_OPER_NOTPRESENT, 34 IF_OPER_DOWN, 35 IF_OPER_LOWERLAYERDOWN, 36 IF_OPER_TESTING, 37 IF_OPER_DORMANT, 38 IF_OPER_UP, 39 }; 40 41 /* link modes */ 42 enum 43 { 44 IF_LINK_MODE_DEFAULT, 45 IF_LINK_MODE_DORMANT, /* limit upward transition to dormant */ 46 }; 47 48 static const char *port_states[] = 49 { 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", 55 }; 56 57 static struct rtnl_handle rth; 58 static struct uloop_fd ufd; 59 60 struct rtnl_handle rth_state; 61 62 static int dump_msg(const struct sockaddr_nl *who, struct nlmsghdr *n, 63 void *arg) 64 { 65 struct ifinfomsg *ifi = NLMSG_DATA(n); 66 struct rtattr * tb[IFLA_MAX + 1]; 67 int len = n->nlmsg_len; 68 char b1[IFNAMSIZ]; 69 int af_family; 70 bool newlink; 71 int br_index; 72 73 if(n->nlmsg_type == NLMSG_DONE) 74 return 0; 75 76 len -= NLMSG_LENGTH(sizeof(*ifi)); 77 if(len < 0) 78 { 79 return -1; 80 } 81 82 af_family = ifi->ifi_family; 83 84 if(af_family != AF_BRIDGE && af_family != AF_UNSPEC) 85 return 0; 86 87 if(n->nlmsg_type != RTM_NEWLINK && n->nlmsg_type != RTM_DELLINK) 88 return 0; 89 90 parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); 91 92 /* Check if we got this from bonding */ 93 if(tb[IFLA_MASTER] && af_family != AF_BRIDGE) 94 return 0; 95 96 if(tb[IFLA_IFNAME] == NULL) 97 { 98 ERROR("BUG: nil ifname\n"); 99 return -1; 100 } 101 102 if(n->nlmsg_type == RTM_DELLINK) 103 LOG("Deleted "); 104 105 LOG("%d: %s ", ifi->ifi_index, (char*)RTA_DATA(tb[IFLA_IFNAME])); 106 107 if(tb[IFLA_OPERSTATE]) 108 { 109 __u8 state = *(__u8*)RTA_DATA(tb[IFLA_OPERSTATE]); 110 switch (state) 111 { 112 case IF_OPER_UNKNOWN: 113 LOG("Unknown "); 114 break; 115 case IF_OPER_NOTPRESENT: 116 LOG("Not Present "); 117 break; 118 case IF_OPER_DOWN: 119 LOG("Down "); 120 break; 121 case IF_OPER_LOWERLAYERDOWN: 122 LOG("Lowerlayerdown "); 123 break; 124 case IF_OPER_TESTING: 125 LOG("Testing "); 126 break; 127 case IF_OPER_DORMANT: 128 LOG("Dormant "); 129 break; 130 case IF_OPER_UP: 131 LOG("Up "); 132 break; 133 default: 134 LOG("State(%d) ", state); 135 } 136 } 137 138 if(tb[IFLA_MTU]) 139 LOG("mtu %u ", *(int*)RTA_DATA(tb[IFLA_MTU])); 140 141 if(tb[IFLA_MASTER]) 142 { 143 LOG("master %s ", 144 if_indextoname(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1)); 145 } 146 147 if(tb[IFLA_PROTINFO]) 148 { 149 uint8_t state = *(uint8_t *)RTA_DATA(tb[IFLA_PROTINFO]); 150 if(state <= BR_STATE_BLOCKING) 151 LOG("state %s", port_states[state]); 152 else 153 LOG("state (%d)", state); 154 } 155 156 newlink = (n->nlmsg_type == RTM_NEWLINK); 157 158 if(tb[IFLA_MASTER]) 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; 162 else 163 br_index = -1; 164 165 bridge_notify(br_index, ifi->ifi_index, newlink, ifi->ifi_flags); 166 167 return 0; 168 } 169 170 void bridge_event_handler(void) 171 { 172 if(rtnl_listen(&rth, dump_msg, stdout) < 0) 173 { 174 ERROR("Error on bridge monitoring socket\n"); 175 } 176 } 177 178 static void bridge_event_cb(struct uloop_fd *fd, unsigned int events) 179 { 180 struct worker_event ev = { 181 .type = WORKER_EV_BRIDGE_EVENT 182 }; 183 184 worker_queue_event(&ev); 185 } 186 187 int init_bridge_ops(void) 188 { 189 if(rtnl_open(&rth, RTMGRP_LINK) < 0) 190 { 191 ERROR("Couldn't open rtnl socket for monitoring\n"); 192 return -1; 193 } 194 195 if(rtnl_open(&rth_state, 0) < 0) 196 { 197 ERROR("Couldn't open rtnl socket for setting state\n"); 198 return -1; 199 } 200 201 if(rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETLINK) < 0) 202 { 203 ERROR("Cannot send dump request: %m\n"); 204 return -1; 205 } 206 207 if(rtnl_dump_filter(&rth, dump_msg, stdout, NULL, NULL) < 0) 208 { 209 ERROR("Dump terminated\n"); 210 return -1; 211 } 212 213 if(fcntl(rth.fd, F_SETFL, O_NONBLOCK) < 0) 214 { 215 ERROR("Error setting O_NONBLOCK: %m\n"); 216 return -1; 217 } 218 219 ufd.fd = rth.fd; 220 ufd.cb = bridge_event_cb; 221 uloop_fd_add(&ufd, ULOOP_READ | ULOOP_EDGE_TRIGGER); 222 bridge_event_cb(&ufd, 0); 223 224 return 0; 225 } 226
This page was automatically generated by LXR 0.3.1. • OpenWrt