1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker * Get/set/delete fdb table with netlink
3*de1e4e89SAndroid Build Coastguard Worker *
4*de1e4e89SAndroid Build Coastguard Worker * TODO: merge/replace this with ip neighbour
5*de1e4e89SAndroid Build Coastguard Worker *
6*de1e4e89SAndroid Build Coastguard Worker * Authors: Stephen Hemminger <[email protected]>
7*de1e4e89SAndroid Build Coastguard Worker */
8*de1e4e89SAndroid Build Coastguard Worker
9*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
10*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
11*de1e4e89SAndroid Build Coastguard Worker #include <unistd.h>
12*de1e4e89SAndroid Build Coastguard Worker #include <netdb.h>
13*de1e4e89SAndroid Build Coastguard Worker #include <time.h>
14*de1e4e89SAndroid Build Coastguard Worker #include <fcntl.h>
15*de1e4e89SAndroid Build Coastguard Worker #include <sys/socket.h>
16*de1e4e89SAndroid Build Coastguard Worker #include <sys/time.h>
17*de1e4e89SAndroid Build Coastguard Worker #include <net/if.h>
18*de1e4e89SAndroid Build Coastguard Worker #include <netinet/in.h>
19*de1e4e89SAndroid Build Coastguard Worker #include <linux/if_bridge.h>
20*de1e4e89SAndroid Build Coastguard Worker #include <linux/if_ether.h>
21*de1e4e89SAndroid Build Coastguard Worker #include <linux/neighbour.h>
22*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
23*de1e4e89SAndroid Build Coastguard Worker #include <limits.h>
24*de1e4e89SAndroid Build Coastguard Worker #include <json_writer.h>
25*de1e4e89SAndroid Build Coastguard Worker #include <stdbool.h>
26*de1e4e89SAndroid Build Coastguard Worker
27*de1e4e89SAndroid Build Coastguard Worker #include "libnetlink.h"
28*de1e4e89SAndroid Build Coastguard Worker #include "br_common.h"
29*de1e4e89SAndroid Build Coastguard Worker #include "rt_names.h"
30*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
31*de1e4e89SAndroid Build Coastguard Worker
32*de1e4e89SAndroid Build Coastguard Worker static unsigned int filter_index, filter_vlan, filter_state;
33*de1e4e89SAndroid Build Coastguard Worker
34*de1e4e89SAndroid Build Coastguard Worker json_writer_t *jw_global;
35*de1e4e89SAndroid Build Coastguard Worker
usage(void)36*de1e4e89SAndroid Build Coastguard Worker static void usage(void)
37*de1e4e89SAndroid Build Coastguard Worker {
38*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr,
39*de1e4e89SAndroid Build Coastguard Worker "Usage: bridge fdb { add | append | del | replace } ADDR dev DEV\n"
40*de1e4e89SAndroid Build Coastguard Worker " [ self ] [ master ] [ use ] [ router ]\n"
41*de1e4e89SAndroid Build Coastguard Worker " [ local | static | dynamic ] [ dst IPADDR ] [ vlan VID ]\n"
42*de1e4e89SAndroid Build Coastguard Worker " [ port PORT] [ vni VNI ] [ via DEV ]\n"
43*de1e4e89SAndroid Build Coastguard Worker " bridge fdb [ show [ br BRDEV ] [ brport DEV ] [ vlan VID ] [ state STATE ] ]\n");
44*de1e4e89SAndroid Build Coastguard Worker exit(-1);
45*de1e4e89SAndroid Build Coastguard Worker }
46*de1e4e89SAndroid Build Coastguard Worker
state_n2a(unsigned int s)47*de1e4e89SAndroid Build Coastguard Worker static const char *state_n2a(unsigned int s)
48*de1e4e89SAndroid Build Coastguard Worker {
49*de1e4e89SAndroid Build Coastguard Worker static char buf[32];
50*de1e4e89SAndroid Build Coastguard Worker
51*de1e4e89SAndroid Build Coastguard Worker if (s & NUD_PERMANENT)
52*de1e4e89SAndroid Build Coastguard Worker return "permanent";
53*de1e4e89SAndroid Build Coastguard Worker
54*de1e4e89SAndroid Build Coastguard Worker if (s & NUD_NOARP)
55*de1e4e89SAndroid Build Coastguard Worker return "static";
56*de1e4e89SAndroid Build Coastguard Worker
57*de1e4e89SAndroid Build Coastguard Worker if (s & NUD_STALE)
58*de1e4e89SAndroid Build Coastguard Worker return "stale";
59*de1e4e89SAndroid Build Coastguard Worker
60*de1e4e89SAndroid Build Coastguard Worker if (s & NUD_REACHABLE)
61*de1e4e89SAndroid Build Coastguard Worker return "";
62*de1e4e89SAndroid Build Coastguard Worker
63*de1e4e89SAndroid Build Coastguard Worker sprintf(buf, "state=%#x", s);
64*de1e4e89SAndroid Build Coastguard Worker return buf;
65*de1e4e89SAndroid Build Coastguard Worker }
66*de1e4e89SAndroid Build Coastguard Worker
state_a2n(unsigned int * s,const char * arg)67*de1e4e89SAndroid Build Coastguard Worker static int state_a2n(unsigned int *s, const char *arg)
68*de1e4e89SAndroid Build Coastguard Worker {
69*de1e4e89SAndroid Build Coastguard Worker if (matches(arg, "permanent") == 0)
70*de1e4e89SAndroid Build Coastguard Worker *s = NUD_PERMANENT;
71*de1e4e89SAndroid Build Coastguard Worker else if (matches(arg, "static") == 0 || matches(arg, "temp") == 0)
72*de1e4e89SAndroid Build Coastguard Worker *s = NUD_NOARP;
73*de1e4e89SAndroid Build Coastguard Worker else if (matches(arg, "stale") == 0)
74*de1e4e89SAndroid Build Coastguard Worker *s = NUD_STALE;
75*de1e4e89SAndroid Build Coastguard Worker else if (matches(arg, "reachable") == 0 || matches(arg, "dynamic") == 0)
76*de1e4e89SAndroid Build Coastguard Worker *s = NUD_REACHABLE;
77*de1e4e89SAndroid Build Coastguard Worker else if (strcmp(arg, "all") == 0)
78*de1e4e89SAndroid Build Coastguard Worker *s = ~0;
79*de1e4e89SAndroid Build Coastguard Worker else if (get_unsigned(s, arg, 0))
80*de1e4e89SAndroid Build Coastguard Worker return -1;
81*de1e4e89SAndroid Build Coastguard Worker
82*de1e4e89SAndroid Build Coastguard Worker return 0;
83*de1e4e89SAndroid Build Coastguard Worker }
84*de1e4e89SAndroid Build Coastguard Worker
start_json_fdb_flags_array(bool * fdb_flags)85*de1e4e89SAndroid Build Coastguard Worker static void start_json_fdb_flags_array(bool *fdb_flags)
86*de1e4e89SAndroid Build Coastguard Worker {
87*de1e4e89SAndroid Build Coastguard Worker if (*fdb_flags)
88*de1e4e89SAndroid Build Coastguard Worker return;
89*de1e4e89SAndroid Build Coastguard Worker jsonw_name(jw_global, "flags");
90*de1e4e89SAndroid Build Coastguard Worker jsonw_start_array(jw_global);
91*de1e4e89SAndroid Build Coastguard Worker *fdb_flags = true;
92*de1e4e89SAndroid Build Coastguard Worker }
93*de1e4e89SAndroid Build Coastguard Worker
print_fdb(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)94*de1e4e89SAndroid Build Coastguard Worker int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
95*de1e4e89SAndroid Build Coastguard Worker {
96*de1e4e89SAndroid Build Coastguard Worker FILE *fp = arg;
97*de1e4e89SAndroid Build Coastguard Worker struct ndmsg *r = NLMSG_DATA(n);
98*de1e4e89SAndroid Build Coastguard Worker int len = n->nlmsg_len;
99*de1e4e89SAndroid Build Coastguard Worker struct rtattr *tb[NDA_MAX+1];
100*de1e4e89SAndroid Build Coastguard Worker __u16 vid = 0;
101*de1e4e89SAndroid Build Coastguard Worker bool fdb_flags = false;
102*de1e4e89SAndroid Build Coastguard Worker const char *state_s;
103*de1e4e89SAndroid Build Coastguard Worker
104*de1e4e89SAndroid Build Coastguard Worker if (n->nlmsg_type != RTM_NEWNEIGH && n->nlmsg_type != RTM_DELNEIGH) {
105*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Not RTM_NEWNEIGH: %08x %08x %08x\n",
106*de1e4e89SAndroid Build Coastguard Worker n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
107*de1e4e89SAndroid Build Coastguard Worker return 0;
108*de1e4e89SAndroid Build Coastguard Worker }
109*de1e4e89SAndroid Build Coastguard Worker
110*de1e4e89SAndroid Build Coastguard Worker len -= NLMSG_LENGTH(sizeof(*r));
111*de1e4e89SAndroid Build Coastguard Worker if (len < 0) {
112*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
113*de1e4e89SAndroid Build Coastguard Worker return -1;
114*de1e4e89SAndroid Build Coastguard Worker }
115*de1e4e89SAndroid Build Coastguard Worker
116*de1e4e89SAndroid Build Coastguard Worker if (r->ndm_family != AF_BRIDGE)
117*de1e4e89SAndroid Build Coastguard Worker return 0;
118*de1e4e89SAndroid Build Coastguard Worker
119*de1e4e89SAndroid Build Coastguard Worker if (filter_index && filter_index != r->ndm_ifindex)
120*de1e4e89SAndroid Build Coastguard Worker return 0;
121*de1e4e89SAndroid Build Coastguard Worker
122*de1e4e89SAndroid Build Coastguard Worker if (filter_state && !(r->ndm_state & filter_state))
123*de1e4e89SAndroid Build Coastguard Worker return 0;
124*de1e4e89SAndroid Build Coastguard Worker
125*de1e4e89SAndroid Build Coastguard Worker parse_rtattr(tb, NDA_MAX, NDA_RTA(r),
126*de1e4e89SAndroid Build Coastguard Worker n->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
127*de1e4e89SAndroid Build Coastguard Worker
128*de1e4e89SAndroid Build Coastguard Worker if (tb[NDA_VLAN])
129*de1e4e89SAndroid Build Coastguard Worker vid = rta_getattr_u16(tb[NDA_VLAN]);
130*de1e4e89SAndroid Build Coastguard Worker
131*de1e4e89SAndroid Build Coastguard Worker if (filter_vlan && filter_vlan != vid)
132*de1e4e89SAndroid Build Coastguard Worker return 0;
133*de1e4e89SAndroid Build Coastguard Worker
134*de1e4e89SAndroid Build Coastguard Worker if (jw_global) {
135*de1e4e89SAndroid Build Coastguard Worker jsonw_pretty(jw_global, 1);
136*de1e4e89SAndroid Build Coastguard Worker jsonw_start_object(jw_global);
137*de1e4e89SAndroid Build Coastguard Worker }
138*de1e4e89SAndroid Build Coastguard Worker
139*de1e4e89SAndroid Build Coastguard Worker if (n->nlmsg_type == RTM_DELNEIGH) {
140*de1e4e89SAndroid Build Coastguard Worker if (jw_global)
141*de1e4e89SAndroid Build Coastguard Worker jsonw_string_field(jw_global, "opCode", "deleted");
142*de1e4e89SAndroid Build Coastguard Worker else
143*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "Deleted ");
144*de1e4e89SAndroid Build Coastguard Worker }
145*de1e4e89SAndroid Build Coastguard Worker
146*de1e4e89SAndroid Build Coastguard Worker if (tb[NDA_LLADDR]) {
147*de1e4e89SAndroid Build Coastguard Worker SPRINT_BUF(b1);
148*de1e4e89SAndroid Build Coastguard Worker ll_addr_n2a(RTA_DATA(tb[NDA_LLADDR]),
149*de1e4e89SAndroid Build Coastguard Worker RTA_PAYLOAD(tb[NDA_LLADDR]),
150*de1e4e89SAndroid Build Coastguard Worker ll_index_to_type(r->ndm_ifindex),
151*de1e4e89SAndroid Build Coastguard Worker b1, sizeof(b1));
152*de1e4e89SAndroid Build Coastguard Worker if (jw_global)
153*de1e4e89SAndroid Build Coastguard Worker jsonw_string_field(jw_global, "mac", b1);
154*de1e4e89SAndroid Build Coastguard Worker else
155*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%s ", b1);
156*de1e4e89SAndroid Build Coastguard Worker }
157*de1e4e89SAndroid Build Coastguard Worker
158*de1e4e89SAndroid Build Coastguard Worker if (!filter_index && r->ndm_ifindex) {
159*de1e4e89SAndroid Build Coastguard Worker if (jw_global)
160*de1e4e89SAndroid Build Coastguard Worker jsonw_string_field(jw_global, "dev",
161*de1e4e89SAndroid Build Coastguard Worker ll_index_to_name(r->ndm_ifindex));
162*de1e4e89SAndroid Build Coastguard Worker else
163*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "dev %s ",
164*de1e4e89SAndroid Build Coastguard Worker ll_index_to_name(r->ndm_ifindex));
165*de1e4e89SAndroid Build Coastguard Worker }
166*de1e4e89SAndroid Build Coastguard Worker
167*de1e4e89SAndroid Build Coastguard Worker if (tb[NDA_DST]) {
168*de1e4e89SAndroid Build Coastguard Worker int family = AF_INET;
169*de1e4e89SAndroid Build Coastguard Worker const char *abuf_s;
170*de1e4e89SAndroid Build Coastguard Worker
171*de1e4e89SAndroid Build Coastguard Worker if (RTA_PAYLOAD(tb[NDA_DST]) == sizeof(struct in6_addr))
172*de1e4e89SAndroid Build Coastguard Worker family = AF_INET6;
173*de1e4e89SAndroid Build Coastguard Worker
174*de1e4e89SAndroid Build Coastguard Worker abuf_s = format_host(family,
175*de1e4e89SAndroid Build Coastguard Worker RTA_PAYLOAD(tb[NDA_DST]),
176*de1e4e89SAndroid Build Coastguard Worker RTA_DATA(tb[NDA_DST]));
177*de1e4e89SAndroid Build Coastguard Worker if (jw_global)
178*de1e4e89SAndroid Build Coastguard Worker jsonw_string_field(jw_global, "dst", abuf_s);
179*de1e4e89SAndroid Build Coastguard Worker else
180*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "dst %s ", abuf_s);
181*de1e4e89SAndroid Build Coastguard Worker }
182*de1e4e89SAndroid Build Coastguard Worker
183*de1e4e89SAndroid Build Coastguard Worker if (vid) {
184*de1e4e89SAndroid Build Coastguard Worker if (jw_global)
185*de1e4e89SAndroid Build Coastguard Worker jsonw_uint_field(jw_global, "vlan", vid);
186*de1e4e89SAndroid Build Coastguard Worker else
187*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "vlan %hu ", vid);
188*de1e4e89SAndroid Build Coastguard Worker }
189*de1e4e89SAndroid Build Coastguard Worker
190*de1e4e89SAndroid Build Coastguard Worker if (tb[NDA_PORT]) {
191*de1e4e89SAndroid Build Coastguard Worker if (jw_global)
192*de1e4e89SAndroid Build Coastguard Worker jsonw_uint_field(jw_global, "port",
193*de1e4e89SAndroid Build Coastguard Worker rta_getattr_be16(tb[NDA_PORT]));
194*de1e4e89SAndroid Build Coastguard Worker else
195*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "port %d ",
196*de1e4e89SAndroid Build Coastguard Worker rta_getattr_be16(tb[NDA_PORT]));
197*de1e4e89SAndroid Build Coastguard Worker }
198*de1e4e89SAndroid Build Coastguard Worker
199*de1e4e89SAndroid Build Coastguard Worker if (tb[NDA_VNI]) {
200*de1e4e89SAndroid Build Coastguard Worker if (jw_global)
201*de1e4e89SAndroid Build Coastguard Worker jsonw_uint_field(jw_global, "vni",
202*de1e4e89SAndroid Build Coastguard Worker rta_getattr_u32(tb[NDA_VNI]));
203*de1e4e89SAndroid Build Coastguard Worker else
204*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "vni %d ",
205*de1e4e89SAndroid Build Coastguard Worker rta_getattr_u32(tb[NDA_VNI]));
206*de1e4e89SAndroid Build Coastguard Worker }
207*de1e4e89SAndroid Build Coastguard Worker
208*de1e4e89SAndroid Build Coastguard Worker if (tb[NDA_IFINDEX]) {
209*de1e4e89SAndroid Build Coastguard Worker unsigned int ifindex = rta_getattr_u32(tb[NDA_IFINDEX]);
210*de1e4e89SAndroid Build Coastguard Worker
211*de1e4e89SAndroid Build Coastguard Worker if (ifindex) {
212*de1e4e89SAndroid Build Coastguard Worker char ifname[IF_NAMESIZE];
213*de1e4e89SAndroid Build Coastguard Worker
214*de1e4e89SAndroid Build Coastguard Worker if (!tb[NDA_LINK_NETNSID] &&
215*de1e4e89SAndroid Build Coastguard Worker if_indextoname(ifindex, ifname)) {
216*de1e4e89SAndroid Build Coastguard Worker if (jw_global)
217*de1e4e89SAndroid Build Coastguard Worker jsonw_string_field(jw_global, "viaIf",
218*de1e4e89SAndroid Build Coastguard Worker ifname);
219*de1e4e89SAndroid Build Coastguard Worker else
220*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "via %s ", ifname);
221*de1e4e89SAndroid Build Coastguard Worker } else {
222*de1e4e89SAndroid Build Coastguard Worker if (jw_global)
223*de1e4e89SAndroid Build Coastguard Worker jsonw_uint_field(jw_global, "viaIfIndex",
224*de1e4e89SAndroid Build Coastguard Worker ifindex);
225*de1e4e89SAndroid Build Coastguard Worker else
226*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "via ifindex %u ", ifindex);
227*de1e4e89SAndroid Build Coastguard Worker }
228*de1e4e89SAndroid Build Coastguard Worker }
229*de1e4e89SAndroid Build Coastguard Worker }
230*de1e4e89SAndroid Build Coastguard Worker
231*de1e4e89SAndroid Build Coastguard Worker if (tb[NDA_LINK_NETNSID]) {
232*de1e4e89SAndroid Build Coastguard Worker if (jw_global)
233*de1e4e89SAndroid Build Coastguard Worker jsonw_uint_field(jw_global, "linkNetNsId",
234*de1e4e89SAndroid Build Coastguard Worker rta_getattr_u32(tb[NDA_LINK_NETNSID]));
235*de1e4e89SAndroid Build Coastguard Worker else
236*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "link-netnsid %d ",
237*de1e4e89SAndroid Build Coastguard Worker rta_getattr_u32(tb[NDA_LINK_NETNSID]));
238*de1e4e89SAndroid Build Coastguard Worker }
239*de1e4e89SAndroid Build Coastguard Worker
240*de1e4e89SAndroid Build Coastguard Worker if (show_stats && tb[NDA_CACHEINFO]) {
241*de1e4e89SAndroid Build Coastguard Worker struct nda_cacheinfo *ci = RTA_DATA(tb[NDA_CACHEINFO]);
242*de1e4e89SAndroid Build Coastguard Worker int hz = get_user_hz();
243*de1e4e89SAndroid Build Coastguard Worker
244*de1e4e89SAndroid Build Coastguard Worker if (jw_global) {
245*de1e4e89SAndroid Build Coastguard Worker jsonw_uint_field(jw_global, "used",
246*de1e4e89SAndroid Build Coastguard Worker ci->ndm_used/hz);
247*de1e4e89SAndroid Build Coastguard Worker jsonw_uint_field(jw_global, "updated",
248*de1e4e89SAndroid Build Coastguard Worker ci->ndm_updated/hz);
249*de1e4e89SAndroid Build Coastguard Worker } else {
250*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "used %d/%d ", ci->ndm_used/hz,
251*de1e4e89SAndroid Build Coastguard Worker ci->ndm_updated/hz);
252*de1e4e89SAndroid Build Coastguard Worker }
253*de1e4e89SAndroid Build Coastguard Worker }
254*de1e4e89SAndroid Build Coastguard Worker
255*de1e4e89SAndroid Build Coastguard Worker if (jw_global) {
256*de1e4e89SAndroid Build Coastguard Worker if (r->ndm_flags & NTF_SELF) {
257*de1e4e89SAndroid Build Coastguard Worker start_json_fdb_flags_array(&fdb_flags);
258*de1e4e89SAndroid Build Coastguard Worker jsonw_string(jw_global, "self");
259*de1e4e89SAndroid Build Coastguard Worker }
260*de1e4e89SAndroid Build Coastguard Worker if (r->ndm_flags & NTF_ROUTER) {
261*de1e4e89SAndroid Build Coastguard Worker start_json_fdb_flags_array(&fdb_flags);
262*de1e4e89SAndroid Build Coastguard Worker jsonw_string(jw_global, "router");
263*de1e4e89SAndroid Build Coastguard Worker }
264*de1e4e89SAndroid Build Coastguard Worker if (r->ndm_flags & NTF_EXT_LEARNED) {
265*de1e4e89SAndroid Build Coastguard Worker start_json_fdb_flags_array(&fdb_flags);
266*de1e4e89SAndroid Build Coastguard Worker jsonw_string(jw_global, "extern_learn");
267*de1e4e89SAndroid Build Coastguard Worker }
268*de1e4e89SAndroid Build Coastguard Worker if (r->ndm_flags & NTF_OFFLOADED) {
269*de1e4e89SAndroid Build Coastguard Worker start_json_fdb_flags_array(&fdb_flags);
270*de1e4e89SAndroid Build Coastguard Worker jsonw_string(jw_global, "offload");
271*de1e4e89SAndroid Build Coastguard Worker }
272*de1e4e89SAndroid Build Coastguard Worker if (r->ndm_flags & NTF_MASTER)
273*de1e4e89SAndroid Build Coastguard Worker jsonw_string(jw_global, "master");
274*de1e4e89SAndroid Build Coastguard Worker if (fdb_flags)
275*de1e4e89SAndroid Build Coastguard Worker jsonw_end_array(jw_global);
276*de1e4e89SAndroid Build Coastguard Worker
277*de1e4e89SAndroid Build Coastguard Worker if (tb[NDA_MASTER])
278*de1e4e89SAndroid Build Coastguard Worker jsonw_string_field(jw_global,
279*de1e4e89SAndroid Build Coastguard Worker "master",
280*de1e4e89SAndroid Build Coastguard Worker ll_index_to_name(rta_getattr_u32(tb[NDA_MASTER])));
281*de1e4e89SAndroid Build Coastguard Worker
282*de1e4e89SAndroid Build Coastguard Worker } else {
283*de1e4e89SAndroid Build Coastguard Worker if (r->ndm_flags & NTF_SELF)
284*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "self ");
285*de1e4e89SAndroid Build Coastguard Worker if (r->ndm_flags & NTF_ROUTER)
286*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "router ");
287*de1e4e89SAndroid Build Coastguard Worker if (r->ndm_flags & NTF_EXT_LEARNED)
288*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "extern_learn ");
289*de1e4e89SAndroid Build Coastguard Worker if (r->ndm_flags & NTF_OFFLOADED)
290*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "offload ");
291*de1e4e89SAndroid Build Coastguard Worker if (tb[NDA_MASTER]) {
292*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "master %s ",
293*de1e4e89SAndroid Build Coastguard Worker ll_index_to_name(rta_getattr_u32(tb[NDA_MASTER])));
294*de1e4e89SAndroid Build Coastguard Worker } else if (r->ndm_flags & NTF_MASTER) {
295*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "master ");
296*de1e4e89SAndroid Build Coastguard Worker }
297*de1e4e89SAndroid Build Coastguard Worker }
298*de1e4e89SAndroid Build Coastguard Worker
299*de1e4e89SAndroid Build Coastguard Worker state_s = state_n2a(r->ndm_state);
300*de1e4e89SAndroid Build Coastguard Worker if (jw_global) {
301*de1e4e89SAndroid Build Coastguard Worker if (state_s[0])
302*de1e4e89SAndroid Build Coastguard Worker jsonw_string_field(jw_global, "state", state_s);
303*de1e4e89SAndroid Build Coastguard Worker
304*de1e4e89SAndroid Build Coastguard Worker jsonw_end_object(jw_global);
305*de1e4e89SAndroid Build Coastguard Worker } else {
306*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%s\n", state_s);
307*de1e4e89SAndroid Build Coastguard Worker
308*de1e4e89SAndroid Build Coastguard Worker fflush(fp);
309*de1e4e89SAndroid Build Coastguard Worker }
310*de1e4e89SAndroid Build Coastguard Worker
311*de1e4e89SAndroid Build Coastguard Worker return 0;
312*de1e4e89SAndroid Build Coastguard Worker }
313*de1e4e89SAndroid Build Coastguard Worker
fdb_show(int argc,char ** argv)314*de1e4e89SAndroid Build Coastguard Worker static int fdb_show(int argc, char **argv)
315*de1e4e89SAndroid Build Coastguard Worker {
316*de1e4e89SAndroid Build Coastguard Worker struct {
317*de1e4e89SAndroid Build Coastguard Worker struct nlmsghdr n;
318*de1e4e89SAndroid Build Coastguard Worker struct ifinfomsg ifm;
319*de1e4e89SAndroid Build Coastguard Worker char buf[256];
320*de1e4e89SAndroid Build Coastguard Worker } req = {
321*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
322*de1e4e89SAndroid Build Coastguard Worker .ifm.ifi_family = PF_BRIDGE,
323*de1e4e89SAndroid Build Coastguard Worker };
324*de1e4e89SAndroid Build Coastguard Worker
325*de1e4e89SAndroid Build Coastguard Worker char *filter_dev = NULL;
326*de1e4e89SAndroid Build Coastguard Worker char *br = NULL;
327*de1e4e89SAndroid Build Coastguard Worker int msg_size = sizeof(struct ifinfomsg);
328*de1e4e89SAndroid Build Coastguard Worker
329*de1e4e89SAndroid Build Coastguard Worker while (argc > 0) {
330*de1e4e89SAndroid Build Coastguard Worker if ((strcmp(*argv, "brport") == 0) || strcmp(*argv, "dev") == 0) {
331*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
332*de1e4e89SAndroid Build Coastguard Worker filter_dev = *argv;
333*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "br") == 0) {
334*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
335*de1e4e89SAndroid Build Coastguard Worker br = *argv;
336*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "vlan") == 0) {
337*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
338*de1e4e89SAndroid Build Coastguard Worker if (filter_vlan)
339*de1e4e89SAndroid Build Coastguard Worker duparg("vlan", *argv);
340*de1e4e89SAndroid Build Coastguard Worker filter_vlan = atoi(*argv);
341*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "state") == 0) {
342*de1e4e89SAndroid Build Coastguard Worker unsigned int state;
343*de1e4e89SAndroid Build Coastguard Worker
344*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
345*de1e4e89SAndroid Build Coastguard Worker if (state_a2n(&state, *argv))
346*de1e4e89SAndroid Build Coastguard Worker invarg("invalid state", *argv);
347*de1e4e89SAndroid Build Coastguard Worker filter_state |= state;
348*de1e4e89SAndroid Build Coastguard Worker } else {
349*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "help") == 0)
350*de1e4e89SAndroid Build Coastguard Worker usage();
351*de1e4e89SAndroid Build Coastguard Worker }
352*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
353*de1e4e89SAndroid Build Coastguard Worker }
354*de1e4e89SAndroid Build Coastguard Worker
355*de1e4e89SAndroid Build Coastguard Worker if (br) {
356*de1e4e89SAndroid Build Coastguard Worker int br_ifindex = ll_name_to_index(br);
357*de1e4e89SAndroid Build Coastguard Worker
358*de1e4e89SAndroid Build Coastguard Worker if (br_ifindex == 0) {
359*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Cannot find bridge device \"%s\"\n", br);
360*de1e4e89SAndroid Build Coastguard Worker return -1;
361*de1e4e89SAndroid Build Coastguard Worker }
362*de1e4e89SAndroid Build Coastguard Worker addattr32(&req.n, sizeof(req), IFLA_MASTER, br_ifindex);
363*de1e4e89SAndroid Build Coastguard Worker msg_size += RTA_LENGTH(4);
364*de1e4e89SAndroid Build Coastguard Worker }
365*de1e4e89SAndroid Build Coastguard Worker
366*de1e4e89SAndroid Build Coastguard Worker /*we'll keep around filter_dev for older kernels */
367*de1e4e89SAndroid Build Coastguard Worker if (filter_dev) {
368*de1e4e89SAndroid Build Coastguard Worker filter_index = if_nametoindex(filter_dev);
369*de1e4e89SAndroid Build Coastguard Worker if (filter_index == 0) {
370*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Cannot find device \"%s\"\n",
371*de1e4e89SAndroid Build Coastguard Worker filter_dev);
372*de1e4e89SAndroid Build Coastguard Worker return -1;
373*de1e4e89SAndroid Build Coastguard Worker }
374*de1e4e89SAndroid Build Coastguard Worker req.ifm.ifi_index = filter_index;
375*de1e4e89SAndroid Build Coastguard Worker }
376*de1e4e89SAndroid Build Coastguard Worker
377*de1e4e89SAndroid Build Coastguard Worker if (rtnl_dump_request(&rth, RTM_GETNEIGH, &req.ifm, msg_size) < 0) {
378*de1e4e89SAndroid Build Coastguard Worker perror("Cannot send dump request");
379*de1e4e89SAndroid Build Coastguard Worker exit(1);
380*de1e4e89SAndroid Build Coastguard Worker }
381*de1e4e89SAndroid Build Coastguard Worker
382*de1e4e89SAndroid Build Coastguard Worker if (json_output) {
383*de1e4e89SAndroid Build Coastguard Worker jw_global = jsonw_new(stdout);
384*de1e4e89SAndroid Build Coastguard Worker if (!jw_global) {
385*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Error allocation json object\n");
386*de1e4e89SAndroid Build Coastguard Worker exit(1);
387*de1e4e89SAndroid Build Coastguard Worker }
388*de1e4e89SAndroid Build Coastguard Worker jsonw_start_array(jw_global);
389*de1e4e89SAndroid Build Coastguard Worker }
390*de1e4e89SAndroid Build Coastguard Worker if (rtnl_dump_filter(&rth, print_fdb, stdout) < 0) {
391*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Dump terminated\n");
392*de1e4e89SAndroid Build Coastguard Worker exit(1);
393*de1e4e89SAndroid Build Coastguard Worker }
394*de1e4e89SAndroid Build Coastguard Worker if (jw_global) {
395*de1e4e89SAndroid Build Coastguard Worker jsonw_end_array(jw_global);
396*de1e4e89SAndroid Build Coastguard Worker jsonw_destroy(&jw_global);
397*de1e4e89SAndroid Build Coastguard Worker }
398*de1e4e89SAndroid Build Coastguard Worker
399*de1e4e89SAndroid Build Coastguard Worker return 0;
400*de1e4e89SAndroid Build Coastguard Worker }
401*de1e4e89SAndroid Build Coastguard Worker
fdb_modify(int cmd,int flags,int argc,char ** argv)402*de1e4e89SAndroid Build Coastguard Worker static int fdb_modify(int cmd, int flags, int argc, char **argv)
403*de1e4e89SAndroid Build Coastguard Worker {
404*de1e4e89SAndroid Build Coastguard Worker struct {
405*de1e4e89SAndroid Build Coastguard Worker struct nlmsghdr n;
406*de1e4e89SAndroid Build Coastguard Worker struct ndmsg ndm;
407*de1e4e89SAndroid Build Coastguard Worker char buf[256];
408*de1e4e89SAndroid Build Coastguard Worker } req = {
409*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)),
410*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_flags = NLM_F_REQUEST | flags,
411*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_type = cmd,
412*de1e4e89SAndroid Build Coastguard Worker .ndm.ndm_family = PF_BRIDGE,
413*de1e4e89SAndroid Build Coastguard Worker .ndm.ndm_state = NUD_NOARP,
414*de1e4e89SAndroid Build Coastguard Worker };
415*de1e4e89SAndroid Build Coastguard Worker char *addr = NULL;
416*de1e4e89SAndroid Build Coastguard Worker char *d = NULL;
417*de1e4e89SAndroid Build Coastguard Worker char abuf[ETH_ALEN];
418*de1e4e89SAndroid Build Coastguard Worker int dst_ok = 0;
419*de1e4e89SAndroid Build Coastguard Worker inet_prefix dst;
420*de1e4e89SAndroid Build Coastguard Worker unsigned long port = 0;
421*de1e4e89SAndroid Build Coastguard Worker unsigned long vni = ~0;
422*de1e4e89SAndroid Build Coastguard Worker unsigned int via = 0;
423*de1e4e89SAndroid Build Coastguard Worker char *endptr;
424*de1e4e89SAndroid Build Coastguard Worker short vid = -1;
425*de1e4e89SAndroid Build Coastguard Worker
426*de1e4e89SAndroid Build Coastguard Worker while (argc > 0) {
427*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "dev") == 0) {
428*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
429*de1e4e89SAndroid Build Coastguard Worker d = *argv;
430*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "dst") == 0) {
431*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
432*de1e4e89SAndroid Build Coastguard Worker if (dst_ok)
433*de1e4e89SAndroid Build Coastguard Worker duparg2("dst", *argv);
434*de1e4e89SAndroid Build Coastguard Worker get_addr(&dst, *argv, preferred_family);
435*de1e4e89SAndroid Build Coastguard Worker dst_ok = 1;
436*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "port") == 0) {
437*de1e4e89SAndroid Build Coastguard Worker
438*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
439*de1e4e89SAndroid Build Coastguard Worker port = strtoul(*argv, &endptr, 0);
440*de1e4e89SAndroid Build Coastguard Worker if (endptr && *endptr) {
441*de1e4e89SAndroid Build Coastguard Worker struct servent *pse;
442*de1e4e89SAndroid Build Coastguard Worker
443*de1e4e89SAndroid Build Coastguard Worker pse = getservbyname(*argv, "udp");
444*de1e4e89SAndroid Build Coastguard Worker if (!pse)
445*de1e4e89SAndroid Build Coastguard Worker invarg("invalid port\n", *argv);
446*de1e4e89SAndroid Build Coastguard Worker port = ntohs(pse->s_port);
447*de1e4e89SAndroid Build Coastguard Worker } else if (port > 0xffff)
448*de1e4e89SAndroid Build Coastguard Worker invarg("invalid port\n", *argv);
449*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "vni") == 0) {
450*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
451*de1e4e89SAndroid Build Coastguard Worker vni = strtoul(*argv, &endptr, 0);
452*de1e4e89SAndroid Build Coastguard Worker if ((endptr && *endptr) ||
453*de1e4e89SAndroid Build Coastguard Worker (vni >> 24) || vni == ULONG_MAX)
454*de1e4e89SAndroid Build Coastguard Worker invarg("invalid VNI\n", *argv);
455*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "via") == 0) {
456*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
457*de1e4e89SAndroid Build Coastguard Worker via = if_nametoindex(*argv);
458*de1e4e89SAndroid Build Coastguard Worker if (via == 0)
459*de1e4e89SAndroid Build Coastguard Worker invarg("invalid device\n", *argv);
460*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "self") == 0) {
461*de1e4e89SAndroid Build Coastguard Worker req.ndm.ndm_flags |= NTF_SELF;
462*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "master") == 0) {
463*de1e4e89SAndroid Build Coastguard Worker req.ndm.ndm_flags |= NTF_MASTER;
464*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "router") == 0) {
465*de1e4e89SAndroid Build Coastguard Worker req.ndm.ndm_flags |= NTF_ROUTER;
466*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "local") == 0 ||
467*de1e4e89SAndroid Build Coastguard Worker matches(*argv, "permanent") == 0) {
468*de1e4e89SAndroid Build Coastguard Worker req.ndm.ndm_state |= NUD_PERMANENT;
469*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "temp") == 0 ||
470*de1e4e89SAndroid Build Coastguard Worker matches(*argv, "static") == 0) {
471*de1e4e89SAndroid Build Coastguard Worker req.ndm.ndm_state |= NUD_REACHABLE;
472*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "dynamic") == 0) {
473*de1e4e89SAndroid Build Coastguard Worker req.ndm.ndm_state |= NUD_REACHABLE;
474*de1e4e89SAndroid Build Coastguard Worker req.ndm.ndm_state &= ~NUD_NOARP;
475*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "vlan") == 0) {
476*de1e4e89SAndroid Build Coastguard Worker if (vid >= 0)
477*de1e4e89SAndroid Build Coastguard Worker duparg2("vlan", *argv);
478*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
479*de1e4e89SAndroid Build Coastguard Worker vid = atoi(*argv);
480*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "use") == 0) {
481*de1e4e89SAndroid Build Coastguard Worker req.ndm.ndm_flags |= NTF_USE;
482*de1e4e89SAndroid Build Coastguard Worker } else {
483*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "to") == 0)
484*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
485*de1e4e89SAndroid Build Coastguard Worker
486*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "help") == 0)
487*de1e4e89SAndroid Build Coastguard Worker usage();
488*de1e4e89SAndroid Build Coastguard Worker if (addr)
489*de1e4e89SAndroid Build Coastguard Worker duparg2("to", *argv);
490*de1e4e89SAndroid Build Coastguard Worker addr = *argv;
491*de1e4e89SAndroid Build Coastguard Worker }
492*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
493*de1e4e89SAndroid Build Coastguard Worker }
494*de1e4e89SAndroid Build Coastguard Worker
495*de1e4e89SAndroid Build Coastguard Worker if (d == NULL || addr == NULL) {
496*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Device and address are required arguments.\n");
497*de1e4e89SAndroid Build Coastguard Worker return -1;
498*de1e4e89SAndroid Build Coastguard Worker }
499*de1e4e89SAndroid Build Coastguard Worker
500*de1e4e89SAndroid Build Coastguard Worker /* Assume self */
501*de1e4e89SAndroid Build Coastguard Worker if (!(req.ndm.ndm_flags&(NTF_SELF|NTF_MASTER)))
502*de1e4e89SAndroid Build Coastguard Worker req.ndm.ndm_flags |= NTF_SELF;
503*de1e4e89SAndroid Build Coastguard Worker
504*de1e4e89SAndroid Build Coastguard Worker /* Assume permanent */
505*de1e4e89SAndroid Build Coastguard Worker if (!(req.ndm.ndm_state&(NUD_PERMANENT|NUD_REACHABLE)))
506*de1e4e89SAndroid Build Coastguard Worker req.ndm.ndm_state |= NUD_PERMANENT;
507*de1e4e89SAndroid Build Coastguard Worker
508*de1e4e89SAndroid Build Coastguard Worker if (sscanf(addr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
509*de1e4e89SAndroid Build Coastguard Worker abuf, abuf+1, abuf+2,
510*de1e4e89SAndroid Build Coastguard Worker abuf+3, abuf+4, abuf+5) != 6) {
511*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Invalid mac address %s\n", addr);
512*de1e4e89SAndroid Build Coastguard Worker return -1;
513*de1e4e89SAndroid Build Coastguard Worker }
514*de1e4e89SAndroid Build Coastguard Worker
515*de1e4e89SAndroid Build Coastguard Worker addattr_l(&req.n, sizeof(req), NDA_LLADDR, abuf, ETH_ALEN);
516*de1e4e89SAndroid Build Coastguard Worker if (dst_ok)
517*de1e4e89SAndroid Build Coastguard Worker addattr_l(&req.n, sizeof(req), NDA_DST, &dst.data, dst.bytelen);
518*de1e4e89SAndroid Build Coastguard Worker
519*de1e4e89SAndroid Build Coastguard Worker if (vid >= 0)
520*de1e4e89SAndroid Build Coastguard Worker addattr16(&req.n, sizeof(req), NDA_VLAN, vid);
521*de1e4e89SAndroid Build Coastguard Worker
522*de1e4e89SAndroid Build Coastguard Worker if (port) {
523*de1e4e89SAndroid Build Coastguard Worker unsigned short dport;
524*de1e4e89SAndroid Build Coastguard Worker
525*de1e4e89SAndroid Build Coastguard Worker dport = htons((unsigned short)port);
526*de1e4e89SAndroid Build Coastguard Worker addattr16(&req.n, sizeof(req), NDA_PORT, dport);
527*de1e4e89SAndroid Build Coastguard Worker }
528*de1e4e89SAndroid Build Coastguard Worker if (vni != ~0)
529*de1e4e89SAndroid Build Coastguard Worker addattr32(&req.n, sizeof(req), NDA_VNI, vni);
530*de1e4e89SAndroid Build Coastguard Worker if (via)
531*de1e4e89SAndroid Build Coastguard Worker addattr32(&req.n, sizeof(req), NDA_IFINDEX, via);
532*de1e4e89SAndroid Build Coastguard Worker
533*de1e4e89SAndroid Build Coastguard Worker req.ndm.ndm_ifindex = ll_name_to_index(d);
534*de1e4e89SAndroid Build Coastguard Worker if (req.ndm.ndm_ifindex == 0) {
535*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Cannot find device \"%s\"\n", d);
536*de1e4e89SAndroid Build Coastguard Worker return -1;
537*de1e4e89SAndroid Build Coastguard Worker }
538*de1e4e89SAndroid Build Coastguard Worker
539*de1e4e89SAndroid Build Coastguard Worker if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
540*de1e4e89SAndroid Build Coastguard Worker return -1;
541*de1e4e89SAndroid Build Coastguard Worker
542*de1e4e89SAndroid Build Coastguard Worker return 0;
543*de1e4e89SAndroid Build Coastguard Worker }
544*de1e4e89SAndroid Build Coastguard Worker
do_fdb(int argc,char ** argv)545*de1e4e89SAndroid Build Coastguard Worker int do_fdb(int argc, char **argv)
546*de1e4e89SAndroid Build Coastguard Worker {
547*de1e4e89SAndroid Build Coastguard Worker ll_init_map(&rth);
548*de1e4e89SAndroid Build Coastguard Worker
549*de1e4e89SAndroid Build Coastguard Worker if (argc > 0) {
550*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "add") == 0)
551*de1e4e89SAndroid Build Coastguard Worker return fdb_modify(RTM_NEWNEIGH, NLM_F_CREATE|NLM_F_EXCL, argc-1, argv+1);
552*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "append") == 0)
553*de1e4e89SAndroid Build Coastguard Worker return fdb_modify(RTM_NEWNEIGH, NLM_F_CREATE|NLM_F_APPEND, argc-1, argv+1);
554*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "replace") == 0)
555*de1e4e89SAndroid Build Coastguard Worker return fdb_modify(RTM_NEWNEIGH, NLM_F_CREATE|NLM_F_REPLACE, argc-1, argv+1);
556*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "delete") == 0)
557*de1e4e89SAndroid Build Coastguard Worker return fdb_modify(RTM_DELNEIGH, 0, argc-1, argv+1);
558*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "show") == 0 ||
559*de1e4e89SAndroid Build Coastguard Worker matches(*argv, "lst") == 0 ||
560*de1e4e89SAndroid Build Coastguard Worker matches(*argv, "list") == 0)
561*de1e4e89SAndroid Build Coastguard Worker return fdb_show(argc-1, argv+1);
562*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "help") == 0)
563*de1e4e89SAndroid Build Coastguard Worker usage();
564*de1e4e89SAndroid Build Coastguard Worker } else
565*de1e4e89SAndroid Build Coastguard Worker return fdb_show(0, NULL);
566*de1e4e89SAndroid Build Coastguard Worker
567*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Command \"%s\" is unknown, try \"bridge fdb help\".\n", *argv);
568*de1e4e89SAndroid Build Coastguard Worker exit(-1);
569*de1e4e89SAndroid Build Coastguard Worker }
570