]> git.ipfire.org Git - people/ms/rstp.git/blame - brmon.c
Merge remote-tracking branch 'upstream/master'
[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
ad02a0eb
SH
33static int dump_msg(const struct sockaddr_nl *who, struct nlmsghdr *n,
34 void *arg)
35{
36 FILE *fp = arg;
37 struct ifinfomsg *ifi = NLMSG_DATA(n);
96e20123 38 struct rtattr * tb[IFLA_MAX+1];
ad02a0eb 39 int len = n->nlmsg_len;
54aa4d79 40 int master = -1;
ad02a0eb 41 char b1[IFNAMSIZ];
ad02a0eb 42
96e20123
SH
43 if (n->nlmsg_type == NLMSG_DONE)
44 return 0;
54aa4d79 45
ad02a0eb 46 len -= NLMSG_LENGTH(sizeof(*ifi));
54aa4d79 47 if (len < 0)
96e20123 48 return -1;
54aa4d79 49
96e20123
SH
50 if (ifi->ifi_family != AF_BRIDGE && ifi->ifi_family != AF_UNSPEC)
51 return 0;
ad02a0eb 52
96e20123
SH
53 if (n->nlmsg_type != RTM_NEWLINK &&
54 n->nlmsg_type != RTM_DELLINK)
55 return 0;
ad02a0eb
SH
56
57 parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
58
96e20123 59 /* Check if we got this from bonding */
54aa4d79
SH
60 if (tb[IFLA_MASTER] && ifi->ifi_family != AF_BRIDGE)
61 return 0;
62
63 /* Check if hearing our own state changes */
64 if (n->nlmsg_type == RTM_NEWLINK && tb[IFLA_PROTINFO]) {
65 uint8_t state = *(uint8_t *)RTA_DATA(tb[IFLA_PROTINFO]);
66
67 if (state != BR_STATE_DISABLED)
68 return 0;
69 }
ad02a0eb 70
ad02a0eb 71 if (tb[IFLA_IFNAME] == NULL) {
54aa4d79
SH
72 fprintf(stderr, "BUG: nil ifname\n");
73 return -1;
ad02a0eb
SH
74 }
75
76 if (n->nlmsg_type == RTM_DELLINK)
54aa4d79 77 fprintf(fp, "Deleted ");
ad02a0eb
SH
78
79 fprintf(fp, "%d: %s ", ifi->ifi_index,
54aa4d79 80 (const char*)RTA_DATA(tb[IFLA_IFNAME]));
ad02a0eb
SH
81
82 if (tb[IFLA_MASTER]) {
54aa4d79
SH
83 master = *(int*)RTA_DATA(tb[IFLA_MASTER]);
84 fprintf(fp, "master %s ", if_indextoname(master, b1));
ad02a0eb
SH
85 }
86
ad02a0eb
SH
87 fprintf(fp, "\n");
88 fflush(fp);
54aa4d79
SH
89
90
91 bridge_notify(master, ifi->ifi_index,
92 (n->nlmsg_type == RTM_NEWLINK),
968d3d40 93 ifi->ifi_flags);
54aa4d79 94
ad02a0eb
SH
95 return 0;
96}
97
98#if 0
99static void usage(void)
100{
101 fprintf(stderr, "Usage: brmon\n");
102 exit(-1);
103}
104
105static int matches(const char *cmd, const char *pattern)
106{
107 int len = strlen(cmd);
108 if (len > strlen(pattern))
109 return -1;
110 return memcmp(pattern, cmd, len);
111}
112
96e20123
SH
113int
114main(int argc, char **argv)
ad02a0eb
SH
115{
116 struct rtnl_handle rth;
117 unsigned groups = ~RTMGRP_TC;
118 int llink = 0;
119 int laddr = 0;
120
121 while (argc > 1) {
122 if (matches(argv[1], "-Version") == 0) {
123 printf("brmon %s\n", SNAPSHOT);
124 exit(0);
125 } else if (matches(argv[1], "link") == 0) {
96e20123 126 llink=1;
ad02a0eb
SH
127 groups = 0;
128 } else if (matches(argv[1], "bridge") == 0) {
96e20123 129 laddr=1;
ad02a0eb
SH
130 groups = 0;
131 } else if (strcmp(argv[1], "all") == 0) {
132 groups = ~RTMGRP_TC;
133 } else if (matches(argv[1], "help") == 0) {
134 usage();
135 } else {
96e20123 136 fprintf(stderr, "Argument \"%s\" is unknown, try \"rtmon help\".\n", argv[1]);
ad02a0eb
SH
137 exit(-1);
138 }
96e20123 139 argc--; argv++;
ad02a0eb
SH
140 }
141
142 if (llink)
143 groups |= RTMGRP_LINK;
144
145 if (rtnl_open(&rth, groups) < 0)
146 exit(1);
147
148 if (rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETLINK) < 0) {
149 perror("Cannot send dump request");
150 exit(1);
151 }
152
153 if (rtnl_dump_filter(&rth, dump_msg, stdout, NULL, NULL) < 0) {
154 fprintf(stderr, "Dump terminated\n");
155 return 1;
156 }
157
158 if (rtnl_listen(&rth, dump_msg, stdout) < 0)
159 exit(2);
160
161 exit(0);
162}
163#endif
164
165#include "bridge_ctl.h"
166#include "epoll_loop.h"
167
168struct rtnl_handle rth;
169struct epoll_event_handler br_handler;
170
171struct rtnl_handle rth_state;
172
173void br_ev_handler(uint32_t events, struct epoll_event_handler *h)
174{
96e20123
SH
175 if (rtnl_listen(&rth, dump_msg, stdout) < 0) {
176 fprintf(stderr, "Error on bridge monitoring socket\n");
177 exit(-1);
178 }
ad02a0eb
SH
179}
180
181int init_bridge_ops(void)
182{
96e20123
SH
183 if (rtnl_open(&rth, ~RTMGRP_TC) < 0) {
184 fprintf(stderr, "Couldn't open rtnl socket for monitoring\n");
185 return -1;
186 }
54aa4d79 187
96e20123
SH
188 if (rtnl_open(&rth_state, 0) < 0) {
189 fprintf(stderr, "Couldn't open rtnl socket for setting state\n");
190 return -1;
191 }
192
193 if (rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETLINK) < 0) {
194 fprintf(stderr, "Cannot send dump request: %m\n");
195 return -1;
196 }
54aa4d79 197
96e20123
SH
198 if (rtnl_dump_filter(&rth, dump_msg, stdout, NULL, NULL) < 0) {
199 fprintf(stderr, "Dump terminated\n");
200 return -1;
201 }
202
203 if (fcntl(rth.fd, F_SETFL, O_NONBLOCK) < 0) {
204 fprintf(stderr, "Error setting O_NONBLOCK: %m\n");
205 return -1;
206 }
207
208 br_handler.fd = rth.fd;
209 br_handler.arg = NULL;
210 br_handler.handler = br_ev_handler;
54aa4d79 211
96e20123
SH
212 if (add_epoll(&br_handler) < 0)
213 return -1;
54aa4d79 214
96e20123 215 return 0;
ad02a0eb
SH
216}
217
218/* Send message. Response is through bridge_notify */
219void bridge_get_configuration(void)
220{
96e20123
SH
221 if (rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETLINK) < 0) {
222 fprintf(stderr, "Cannot send dump request: %m\n");
223 }
ad02a0eb 224}