• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/ustp/brmon.c

  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