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