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