]> git.ipfire.org Git - people/ms/rstp.git/blob - brmon.c
reindent source
[people/ms/rstp.git] / 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 *
11 * Modified by Srinivas Aji <Aji_Srinivas@emc.com> for use
12 * in RSTP daemon. - 2006-09-01
13 */
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <syslog.h>
19 #include <fcntl.h>
20 #include <sys/socket.h>
21 #include <sys/time.h>
22 #include <net/if.h>
23 #include <netinet/in.h>
24 #include <linux/if_bridge.h>
25 #include <string.h>
26
27 #include "libnetlink.h"
28
29 #include "bridge_ctl.h"
30
31 static const char SNAPSHOT[] = "v0.1";
32
33 /* RFC 2863 operational status */
34 enum {
35 IF_OPER_UNKNOWN,
36 IF_OPER_NOTPRESENT,
37 IF_OPER_DOWN,
38 IF_OPER_LOWERLAYERDOWN,
39 IF_OPER_TESTING,
40 IF_OPER_DORMANT,
41 IF_OPER_UP,
42 };
43
44 /* link modes */
45 enum {
46 IF_LINK_MODE_DEFAULT,
47 IF_LINK_MODE_DORMANT, /* limit upward transition to dormant */
48 };
49
50 static const char *port_states[] = {
51 [BR_STATE_DISABLED] = "disabled",
52 [BR_STATE_LISTENING] = "listening",
53 [BR_STATE_LEARNING] = "learning",
54 [BR_STATE_FORWARDING] = "forwarding",
55 [BR_STATE_BLOCKING] = "blocking",
56 };
57
58 static int dump_msg(const struct sockaddr_nl *who, struct nlmsghdr *n,
59 void *arg)
60 {
61 FILE *fp = arg;
62 struct ifinfomsg *ifi = NLMSG_DATA(n);
63 struct rtattr *tb[IFLA_MAX + 1];
64 int len = n->nlmsg_len;
65 char b1[IFNAMSIZ];
66 int af_family = ifi->ifi_family;
67
68 if (n->nlmsg_type == NLMSG_DONE)
69 return 0;
70
71 len -= NLMSG_LENGTH(sizeof(*ifi));
72 if (len < 0) {
73 return -1;
74 }
75 #if 0
76
77 if (filter.ifindex && ifi->ifi_index != filter.ifindex)
78 return 0;
79
80 if (filter.up && !(ifi->ifi_flags & IFF_UP))
81 return 0;
82 #endif
83 if (ifi->ifi_family != AF_BRIDGE && ifi->ifi_family != AF_UNSPEC)
84 return 0;
85
86 if (n->nlmsg_type != RTM_NEWLINK && n->nlmsg_type != RTM_DELLINK)
87 return 0;
88
89 parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
90
91 /* Check if we got this from bonding */
92 if (tb[IFLA_MASTER] && af_family != AF_BRIDGE)
93 return 0;
94
95 /* Check for BPDU */
96 if (tb[IFLA_PRIORITY] && af_family == AF_BRIDGE) {
97 bridge_bpdu_rcv(ifi->ifi_index,
98 RTA_DATA(tb[IFLA_PRIORITY]),
99 RTA_PAYLOAD(tb[IFLA_PRIORITY]));
100 return 0;
101 }
102
103 if (tb[IFLA_IFNAME] == NULL) {
104 fprintf(stderr, "BUG: nil ifname\n");
105 return -1;
106 }
107
108 if (n->nlmsg_type == RTM_DELLINK)
109 fprintf(fp, "Deleted ");
110
111 fprintf(fp, "%d: %s ", ifi->ifi_index,
112 tb[IFLA_IFNAME] ? (char *)RTA_DATA(tb[IFLA_IFNAME]) : "<nil>");
113
114 if (tb[IFLA_OPERSTATE]) {
115 int state = *(int *)RTA_DATA(tb[IFLA_OPERSTATE]);
116 switch (state) {
117 case IF_OPER_UNKNOWN:
118 fprintf(fp, "Unknown ");
119 break;
120 case IF_OPER_NOTPRESENT:
121 fprintf(fp, "Not Present ");
122 break;
123 case IF_OPER_DOWN:
124 fprintf(fp, "Down ");
125 break;
126 case IF_OPER_LOWERLAYERDOWN:
127 fprintf(fp, "Lowerlayerdown ");
128 break;
129 case IF_OPER_TESTING:
130 fprintf(fp, "Testing ");
131 break;
132 case IF_OPER_DORMANT:
133 fprintf(fp, "Dormant ");
134 break;
135 case IF_OPER_UP:
136 fprintf(fp, "Up ");
137 break;
138 default:
139 fprintf(fp, "State(%d) ", state);
140 }
141 }
142
143 if (tb[IFLA_MTU])
144 fprintf(fp, "mtu %u ", *(int *)RTA_DATA(tb[IFLA_MTU]));
145
146 if (tb[IFLA_MASTER]) {
147 fprintf(fp, "master %s ",
148 if_indextoname(*(int *)RTA_DATA(tb[IFLA_MASTER]), b1));
149 }
150
151 if (tb[IFLA_PROTINFO]) {
152 uint8_t state = *(uint8_t *) RTA_DATA(tb[IFLA_PROTINFO]);
153 if (state <= BR_STATE_BLOCKING)
154 fprintf(fp, "state %s", port_states[state]);
155 else
156 fprintf(fp, "state (%d)", state);
157 }
158
159 fprintf(fp, "\n");
160 fflush(fp);
161 {
162 int newlink = (n->nlmsg_type == RTM_NEWLINK);
163 int up = 0;
164 if (newlink && tb[IFLA_OPERSTATE]) {
165 int state = *(int *)RTA_DATA(tb[IFLA_OPERSTATE]);
166 up = (state == IF_OPER_UP)
167 || (state == IF_OPER_UNKNOWN);
168 }
169
170 bridge_notify((tb[IFLA_MASTER] ? *(int *)
171 RTA_DATA(tb[IFLA_MASTER]) : -1), ifi->ifi_index,
172 newlink, up);
173 }
174 return 0;
175 }
176
177 #if 0
178 static void usage(void)
179 {
180 fprintf(stderr, "Usage: brmon\n");
181 exit(-1);
182 }
183
184 static int matches(const char *cmd, const char *pattern)
185 {
186 int len = strlen(cmd);
187 if (len > strlen(pattern))
188 return -1;
189 return memcmp(pattern, cmd, len);
190 }
191
192 int main(int argc, char **argv)
193 {
194 struct rtnl_handle rth;
195 unsigned groups = ~RTMGRP_TC;
196 int llink = 0;
197 int laddr = 0;
198
199 while (argc > 1) {
200 if (matches(argv[1], "-Version") == 0) {
201 printf("brmon %s\n", SNAPSHOT);
202 exit(0);
203 } else if (matches(argv[1], "link") == 0) {
204 llink = 1;
205 groups = 0;
206 } else if (matches(argv[1], "bridge") == 0) {
207 laddr = 1;
208 groups = 0;
209 } else if (strcmp(argv[1], "all") == 0) {
210 groups = ~RTMGRP_TC;
211 } else if (matches(argv[1], "help") == 0) {
212 usage();
213 } else {
214 fprintf(stderr,
215 "Argument \"%s\" is unknown, try \"rtmon help\".\n",
216 argv[1]);
217 exit(-1);
218 }
219 argc--;
220 argv++;
221 }
222
223 if (llink)
224 groups |= RTMGRP_LINK;
225
226 if (rtnl_open(&rth, groups) < 0)
227 exit(1);
228
229 if (rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETLINK) < 0) {
230 perror("Cannot send dump request");
231 exit(1);
232 }
233
234 if (rtnl_dump_filter(&rth, dump_msg, stdout, NULL, NULL) < 0) {
235 fprintf(stderr, "Dump terminated\n");
236 return 1;
237 }
238
239 if (rtnl_listen(&rth, dump_msg, stdout) < 0)
240 exit(2);
241
242 exit(0);
243 }
244 #endif
245
246 #include "bridge_ctl.h"
247 #include "epoll_loop.h"
248
249 struct rtnl_handle rth;
250 struct epoll_event_handler br_handler;
251
252 struct rtnl_handle rth_state;
253
254 void br_ev_handler(uint32_t events, struct epoll_event_handler *h)
255 {
256 if (rtnl_listen(&rth, dump_msg, stdout) < 0) {
257 fprintf(stderr, "Error on bridge monitoring socket\n");
258 exit(-1);
259 }
260 }
261
262 int init_bridge_ops(void)
263 {
264 if (rtnl_open(&rth, ~RTMGRP_TC) < 0) {
265 fprintf(stderr, "Couldn't open rtnl socket for monitoring\n");
266 return -1;
267 }
268
269 if (rtnl_open(&rth_state, 0) < 0) {
270 fprintf(stderr,
271 "Couldn't open rtnl socket for setting state\n");
272 return -1;
273 }
274
275 if (rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETLINK) < 0) {
276 fprintf(stderr, "Cannot send dump request: %m\n");
277 return -1;
278 }
279
280 if (rtnl_dump_filter(&rth, dump_msg, stdout, NULL, NULL) < 0) {
281 fprintf(stderr, "Dump terminated\n");
282 return -1;
283 }
284
285 if (fcntl(rth.fd, F_SETFL, O_NONBLOCK) < 0) {
286 fprintf(stderr, "Error setting O_NONBLOCK: %m\n");
287 return -1;
288 }
289
290 br_handler.fd = rth.fd;
291 br_handler.arg = NULL;
292 br_handler.handler = br_ev_handler;
293
294 if (add_epoll(&br_handler) < 0)
295 return -1;
296
297 return 0;
298 }
299
300 /* Send message. Response is through bridge_notify */
301 void bridge_get_configuration(void)
302 {
303 if (rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETLINK) < 0) {
304 fprintf(stderr, "Cannot send dump request: %m\n");
305 }
306 }