1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker * ipmroute.c "ip mroute".
3*de1e4e89SAndroid Build Coastguard Worker *
4*de1e4e89SAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or
5*de1e4e89SAndroid Build Coastguard Worker * modify it under the terms of the GNU General Public License
6*de1e4e89SAndroid Build Coastguard Worker * as published by the Free Software Foundation; either version
7*de1e4e89SAndroid Build Coastguard Worker * 2 of the License, or (at your option) any later version.
8*de1e4e89SAndroid Build Coastguard Worker *
9*de1e4e89SAndroid Build Coastguard Worker * Authors: Alexey Kuznetsov, <[email protected]>
10*de1e4e89SAndroid Build Coastguard Worker *
11*de1e4e89SAndroid Build Coastguard Worker */
12*de1e4e89SAndroid Build Coastguard Worker
13*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
14*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
15*de1e4e89SAndroid Build Coastguard Worker #include <unistd.h>
16*de1e4e89SAndroid Build Coastguard Worker #include <syslog.h>
17*de1e4e89SAndroid Build Coastguard Worker #include <fcntl.h>
18*de1e4e89SAndroid Build Coastguard Worker #include <inttypes.h>
19*de1e4e89SAndroid Build Coastguard Worker #include <sys/ioctl.h>
20*de1e4e89SAndroid Build Coastguard Worker #include <sys/socket.h>
21*de1e4e89SAndroid Build Coastguard Worker #include <netinet/in.h>
22*de1e4e89SAndroid Build Coastguard Worker #include <arpa/inet.h>
23*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
24*de1e4e89SAndroid Build Coastguard Worker
25*de1e4e89SAndroid Build Coastguard Worker #include <linux/netdevice.h>
26*de1e4e89SAndroid Build Coastguard Worker #include <linux/if.h>
27*de1e4e89SAndroid Build Coastguard Worker #include <linux/if_arp.h>
28*de1e4e89SAndroid Build Coastguard Worker #include <linux/sockios.h>
29*de1e4e89SAndroid Build Coastguard Worker
30*de1e4e89SAndroid Build Coastguard Worker #include <rt_names.h>
31*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
32*de1e4e89SAndroid Build Coastguard Worker #include "ip_common.h"
33*de1e4e89SAndroid Build Coastguard Worker
34*de1e4e89SAndroid Build Coastguard Worker static void usage(void) __attribute__((noreturn));
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, "Usage: ip mroute show [ [ to ] PREFIX ] [ from PREFIX ] [ iif DEVICE ]\n");
39*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " [ table TABLE_ID ]\n");
40*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "TABLE_ID := [ local | main | default | all | NUMBER ]\n");
41*de1e4e89SAndroid Build Coastguard Worker #if 0
42*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Usage: ip mroute [ add | del ] DESTINATION from SOURCE [ iif DEVICE ] [ oif DEVICE ]\n");
43*de1e4e89SAndroid Build Coastguard Worker #endif
44*de1e4e89SAndroid Build Coastguard Worker exit(-1);
45*de1e4e89SAndroid Build Coastguard Worker }
46*de1e4e89SAndroid Build Coastguard Worker
47*de1e4e89SAndroid Build Coastguard Worker struct rtfilter {
48*de1e4e89SAndroid Build Coastguard Worker int tb;
49*de1e4e89SAndroid Build Coastguard Worker int af;
50*de1e4e89SAndroid Build Coastguard Worker int iif;
51*de1e4e89SAndroid Build Coastguard Worker inet_prefix mdst;
52*de1e4e89SAndroid Build Coastguard Worker inet_prefix msrc;
53*de1e4e89SAndroid Build Coastguard Worker } filter;
54*de1e4e89SAndroid Build Coastguard Worker
print_mroute(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)55*de1e4e89SAndroid Build Coastguard Worker int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
56*de1e4e89SAndroid Build Coastguard Worker {
57*de1e4e89SAndroid Build Coastguard Worker FILE *fp = (FILE *)arg;
58*de1e4e89SAndroid Build Coastguard Worker struct rtmsg *r = NLMSG_DATA(n);
59*de1e4e89SAndroid Build Coastguard Worker int len = n->nlmsg_len;
60*de1e4e89SAndroid Build Coastguard Worker struct rtattr *tb[RTA_MAX+1];
61*de1e4e89SAndroid Build Coastguard Worker char obuf[256];
62*de1e4e89SAndroid Build Coastguard Worker
63*de1e4e89SAndroid Build Coastguard Worker SPRINT_BUF(b1);
64*de1e4e89SAndroid Build Coastguard Worker __u32 table;
65*de1e4e89SAndroid Build Coastguard Worker int iif = 0;
66*de1e4e89SAndroid Build Coastguard Worker int family;
67*de1e4e89SAndroid Build Coastguard Worker
68*de1e4e89SAndroid Build Coastguard Worker if ((n->nlmsg_type != RTM_NEWROUTE &&
69*de1e4e89SAndroid Build Coastguard Worker n->nlmsg_type != RTM_DELROUTE)) {
70*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Not a multicast route: %08x %08x %08x\n",
71*de1e4e89SAndroid Build Coastguard Worker n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
72*de1e4e89SAndroid Build Coastguard Worker return 0;
73*de1e4e89SAndroid Build Coastguard Worker }
74*de1e4e89SAndroid Build Coastguard Worker len -= NLMSG_LENGTH(sizeof(*r));
75*de1e4e89SAndroid Build Coastguard Worker if (len < 0) {
76*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
77*de1e4e89SAndroid Build Coastguard Worker return -1;
78*de1e4e89SAndroid Build Coastguard Worker }
79*de1e4e89SAndroid Build Coastguard Worker if (r->rtm_type != RTN_MULTICAST) {
80*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Not a multicast route (type: %s)\n",
81*de1e4e89SAndroid Build Coastguard Worker rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1)));
82*de1e4e89SAndroid Build Coastguard Worker return 0;
83*de1e4e89SAndroid Build Coastguard Worker }
84*de1e4e89SAndroid Build Coastguard Worker
85*de1e4e89SAndroid Build Coastguard Worker parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
86*de1e4e89SAndroid Build Coastguard Worker table = rtm_get_table(r, tb);
87*de1e4e89SAndroid Build Coastguard Worker
88*de1e4e89SAndroid Build Coastguard Worker if (filter.tb > 0 && filter.tb != table)
89*de1e4e89SAndroid Build Coastguard Worker return 0;
90*de1e4e89SAndroid Build Coastguard Worker
91*de1e4e89SAndroid Build Coastguard Worker if (tb[RTA_IIF])
92*de1e4e89SAndroid Build Coastguard Worker iif = rta_getattr_u32(tb[RTA_IIF]);
93*de1e4e89SAndroid Build Coastguard Worker if (filter.iif && filter.iif != iif)
94*de1e4e89SAndroid Build Coastguard Worker return 0;
95*de1e4e89SAndroid Build Coastguard Worker
96*de1e4e89SAndroid Build Coastguard Worker if (filter.af && filter.af != r->rtm_family)
97*de1e4e89SAndroid Build Coastguard Worker return 0;
98*de1e4e89SAndroid Build Coastguard Worker
99*de1e4e89SAndroid Build Coastguard Worker if (tb[RTA_DST] && filter.mdst.bitlen > 0) {
100*de1e4e89SAndroid Build Coastguard Worker inet_prefix dst = { .family = r->rtm_family };
101*de1e4e89SAndroid Build Coastguard Worker
102*de1e4e89SAndroid Build Coastguard Worker memcpy(&dst.data, RTA_DATA(tb[RTA_DST]), RTA_PAYLOAD(tb[RTA_DST]));
103*de1e4e89SAndroid Build Coastguard Worker if (inet_addr_match(&dst, &filter.mdst, filter.mdst.bitlen))
104*de1e4e89SAndroid Build Coastguard Worker return 0;
105*de1e4e89SAndroid Build Coastguard Worker }
106*de1e4e89SAndroid Build Coastguard Worker
107*de1e4e89SAndroid Build Coastguard Worker if (tb[RTA_SRC] && filter.msrc.bitlen > 0) {
108*de1e4e89SAndroid Build Coastguard Worker inet_prefix src = { .family = r->rtm_family };
109*de1e4e89SAndroid Build Coastguard Worker
110*de1e4e89SAndroid Build Coastguard Worker memcpy(&src.data, RTA_DATA(tb[RTA_SRC]), RTA_PAYLOAD(tb[RTA_SRC]));
111*de1e4e89SAndroid Build Coastguard Worker if (inet_addr_match(&src, &filter.msrc, filter.msrc.bitlen))
112*de1e4e89SAndroid Build Coastguard Worker return 0;
113*de1e4e89SAndroid Build Coastguard Worker }
114*de1e4e89SAndroid Build Coastguard Worker
115*de1e4e89SAndroid Build Coastguard Worker family = get_real_family(r->rtm_type, r->rtm_family);
116*de1e4e89SAndroid Build Coastguard Worker
117*de1e4e89SAndroid Build Coastguard Worker if (n->nlmsg_type == RTM_DELROUTE)
118*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "Deleted ");
119*de1e4e89SAndroid Build Coastguard Worker
120*de1e4e89SAndroid Build Coastguard Worker if (tb[RTA_SRC])
121*de1e4e89SAndroid Build Coastguard Worker len = snprintf(obuf, sizeof(obuf),
122*de1e4e89SAndroid Build Coastguard Worker "(%s, ", rt_addr_n2a_rta(family, tb[RTA_SRC]));
123*de1e4e89SAndroid Build Coastguard Worker else
124*de1e4e89SAndroid Build Coastguard Worker len = sprintf(obuf, "(unknown, ");
125*de1e4e89SAndroid Build Coastguard Worker if (tb[RTA_DST])
126*de1e4e89SAndroid Build Coastguard Worker snprintf(obuf + len, sizeof(obuf) - len,
127*de1e4e89SAndroid Build Coastguard Worker "%s)", rt_addr_n2a_rta(family, tb[RTA_DST]));
128*de1e4e89SAndroid Build Coastguard Worker else
129*de1e4e89SAndroid Build Coastguard Worker snprintf(obuf + len, sizeof(obuf) - len, "unknown) ");
130*de1e4e89SAndroid Build Coastguard Worker
131*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%-32s Iif: ", obuf);
132*de1e4e89SAndroid Build Coastguard Worker if (iif)
133*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%-10s ", ll_index_to_name(iif));
134*de1e4e89SAndroid Build Coastguard Worker else
135*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "unresolved ");
136*de1e4e89SAndroid Build Coastguard Worker
137*de1e4e89SAndroid Build Coastguard Worker if (tb[RTA_MULTIPATH]) {
138*de1e4e89SAndroid Build Coastguard Worker struct rtnexthop *nh = RTA_DATA(tb[RTA_MULTIPATH]);
139*de1e4e89SAndroid Build Coastguard Worker int first = 1;
140*de1e4e89SAndroid Build Coastguard Worker
141*de1e4e89SAndroid Build Coastguard Worker len = RTA_PAYLOAD(tb[RTA_MULTIPATH]);
142*de1e4e89SAndroid Build Coastguard Worker
143*de1e4e89SAndroid Build Coastguard Worker for (;;) {
144*de1e4e89SAndroid Build Coastguard Worker if (len < sizeof(*nh))
145*de1e4e89SAndroid Build Coastguard Worker break;
146*de1e4e89SAndroid Build Coastguard Worker if (nh->rtnh_len > len)
147*de1e4e89SAndroid Build Coastguard Worker break;
148*de1e4e89SAndroid Build Coastguard Worker
149*de1e4e89SAndroid Build Coastguard Worker if (first) {
150*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "Oifs: ");
151*de1e4e89SAndroid Build Coastguard Worker first = 0;
152*de1e4e89SAndroid Build Coastguard Worker }
153*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%s", ll_index_to_name(nh->rtnh_ifindex));
154*de1e4e89SAndroid Build Coastguard Worker if (nh->rtnh_hops > 1)
155*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "(ttl %d) ", nh->rtnh_hops);
156*de1e4e89SAndroid Build Coastguard Worker else
157*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, " ");
158*de1e4e89SAndroid Build Coastguard Worker len -= NLMSG_ALIGN(nh->rtnh_len);
159*de1e4e89SAndroid Build Coastguard Worker nh = RTNH_NEXT(nh);
160*de1e4e89SAndroid Build Coastguard Worker }
161*de1e4e89SAndroid Build Coastguard Worker }
162*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, " State: %s",
163*de1e4e89SAndroid Build Coastguard Worker r->rtm_flags & RTNH_F_UNRESOLVED ? "unresolved" : "resolved");
164*de1e4e89SAndroid Build Coastguard Worker if (show_stats && tb[RTA_MFC_STATS]) {
165*de1e4e89SAndroid Build Coastguard Worker struct rta_mfc_stats *mfcs = RTA_DATA(tb[RTA_MFC_STATS]);
166*de1e4e89SAndroid Build Coastguard Worker
167*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%s %"PRIu64" packets, %"PRIu64" bytes", _SL_,
168*de1e4e89SAndroid Build Coastguard Worker (uint64_t)mfcs->mfcs_packets,
169*de1e4e89SAndroid Build Coastguard Worker (uint64_t)mfcs->mfcs_bytes);
170*de1e4e89SAndroid Build Coastguard Worker if (mfcs->mfcs_wrong_if)
171*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, ", %"PRIu64" arrived on wrong iif.",
172*de1e4e89SAndroid Build Coastguard Worker (uint64_t)mfcs->mfcs_wrong_if);
173*de1e4e89SAndroid Build Coastguard Worker }
174*de1e4e89SAndroid Build Coastguard Worker if (show_stats && tb[RTA_EXPIRES]) {
175*de1e4e89SAndroid Build Coastguard Worker struct timeval tv;
176*de1e4e89SAndroid Build Coastguard Worker
177*de1e4e89SAndroid Build Coastguard Worker __jiffies_to_tv(&tv, rta_getattr_u64(tb[RTA_EXPIRES]));
178*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, ", Age %4i.%.2i", (int)tv.tv_sec,
179*de1e4e89SAndroid Build Coastguard Worker (int)tv.tv_usec/10000);
180*de1e4e89SAndroid Build Coastguard Worker }
181*de1e4e89SAndroid Build Coastguard Worker
182*de1e4e89SAndroid Build Coastguard Worker if (table && (table != RT_TABLE_MAIN || show_details > 0) && !filter.tb)
183*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, " Table: %s",
184*de1e4e89SAndroid Build Coastguard Worker rtnl_rttable_n2a(table, b1, sizeof(b1)));
185*de1e4e89SAndroid Build Coastguard Worker
186*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "\n");
187*de1e4e89SAndroid Build Coastguard Worker fflush(fp);
188*de1e4e89SAndroid Build Coastguard Worker return 0;
189*de1e4e89SAndroid Build Coastguard Worker }
190*de1e4e89SAndroid Build Coastguard Worker
ipmroute_reset_filter(int ifindex)191*de1e4e89SAndroid Build Coastguard Worker void ipmroute_reset_filter(int ifindex)
192*de1e4e89SAndroid Build Coastguard Worker {
193*de1e4e89SAndroid Build Coastguard Worker memset(&filter, 0, sizeof(filter));
194*de1e4e89SAndroid Build Coastguard Worker filter.mdst.bitlen = -1;
195*de1e4e89SAndroid Build Coastguard Worker filter.msrc.bitlen = -1;
196*de1e4e89SAndroid Build Coastguard Worker filter.iif = ifindex;
197*de1e4e89SAndroid Build Coastguard Worker }
198*de1e4e89SAndroid Build Coastguard Worker
mroute_list(int argc,char ** argv)199*de1e4e89SAndroid Build Coastguard Worker static int mroute_list(int argc, char **argv)
200*de1e4e89SAndroid Build Coastguard Worker {
201*de1e4e89SAndroid Build Coastguard Worker char *id = NULL;
202*de1e4e89SAndroid Build Coastguard Worker int family;
203*de1e4e89SAndroid Build Coastguard Worker
204*de1e4e89SAndroid Build Coastguard Worker ipmroute_reset_filter(0);
205*de1e4e89SAndroid Build Coastguard Worker if (preferred_family == AF_UNSPEC)
206*de1e4e89SAndroid Build Coastguard Worker family = AF_INET;
207*de1e4e89SAndroid Build Coastguard Worker else
208*de1e4e89SAndroid Build Coastguard Worker family = AF_INET6;
209*de1e4e89SAndroid Build Coastguard Worker if (family == AF_INET) {
210*de1e4e89SAndroid Build Coastguard Worker filter.af = RTNL_FAMILY_IPMR;
211*de1e4e89SAndroid Build Coastguard Worker filter.tb = RT_TABLE_DEFAULT; /* for backward compatibility */
212*de1e4e89SAndroid Build Coastguard Worker } else
213*de1e4e89SAndroid Build Coastguard Worker filter.af = RTNL_FAMILY_IP6MR;
214*de1e4e89SAndroid Build Coastguard Worker
215*de1e4e89SAndroid Build Coastguard Worker while (argc > 0) {
216*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "table") == 0) {
217*de1e4e89SAndroid Build Coastguard Worker __u32 tid;
218*de1e4e89SAndroid Build Coastguard Worker
219*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
220*de1e4e89SAndroid Build Coastguard Worker if (rtnl_rttable_a2n(&tid, *argv)) {
221*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "all") == 0) {
222*de1e4e89SAndroid Build Coastguard Worker filter.tb = 0;
223*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "help") == 0) {
224*de1e4e89SAndroid Build Coastguard Worker usage();
225*de1e4e89SAndroid Build Coastguard Worker } else {
226*de1e4e89SAndroid Build Coastguard Worker invarg("table id value is invalid\n", *argv);
227*de1e4e89SAndroid Build Coastguard Worker }
228*de1e4e89SAndroid Build Coastguard Worker } else
229*de1e4e89SAndroid Build Coastguard Worker filter.tb = tid;
230*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "iif") == 0) {
231*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
232*de1e4e89SAndroid Build Coastguard Worker id = *argv;
233*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "from") == 0) {
234*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
235*de1e4e89SAndroid Build Coastguard Worker get_prefix(&filter.msrc, *argv, family);
236*de1e4e89SAndroid Build Coastguard Worker } else {
237*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "to") == 0) {
238*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
239*de1e4e89SAndroid Build Coastguard Worker }
240*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "help") == 0)
241*de1e4e89SAndroid Build Coastguard Worker usage();
242*de1e4e89SAndroid Build Coastguard Worker get_prefix(&filter.mdst, *argv, family);
243*de1e4e89SAndroid Build Coastguard Worker }
244*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
245*de1e4e89SAndroid Build Coastguard Worker }
246*de1e4e89SAndroid Build Coastguard Worker
247*de1e4e89SAndroid Build Coastguard Worker ll_init_map(&rth);
248*de1e4e89SAndroid Build Coastguard Worker
249*de1e4e89SAndroid Build Coastguard Worker if (id) {
250*de1e4e89SAndroid Build Coastguard Worker int idx;
251*de1e4e89SAndroid Build Coastguard Worker
252*de1e4e89SAndroid Build Coastguard Worker if ((idx = ll_name_to_index(id)) == 0) {
253*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Cannot find device \"%s\"\n", id);
254*de1e4e89SAndroid Build Coastguard Worker return -1;
255*de1e4e89SAndroid Build Coastguard Worker }
256*de1e4e89SAndroid Build Coastguard Worker filter.iif = idx;
257*de1e4e89SAndroid Build Coastguard Worker }
258*de1e4e89SAndroid Build Coastguard Worker
259*de1e4e89SAndroid Build Coastguard Worker if (rtnl_wilddump_request(&rth, filter.af, RTM_GETROUTE) < 0) {
260*de1e4e89SAndroid Build Coastguard Worker perror("Cannot send dump request");
261*de1e4e89SAndroid Build Coastguard Worker return 1;
262*de1e4e89SAndroid Build Coastguard Worker }
263*de1e4e89SAndroid Build Coastguard Worker
264*de1e4e89SAndroid Build Coastguard Worker if (rtnl_dump_filter(&rth, print_mroute, stdout) < 0) {
265*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Dump terminated\n");
266*de1e4e89SAndroid Build Coastguard Worker exit(1);
267*de1e4e89SAndroid Build Coastguard Worker }
268*de1e4e89SAndroid Build Coastguard Worker
269*de1e4e89SAndroid Build Coastguard Worker exit(0);
270*de1e4e89SAndroid Build Coastguard Worker }
271*de1e4e89SAndroid Build Coastguard Worker
do_multiroute(int argc,char ** argv)272*de1e4e89SAndroid Build Coastguard Worker int do_multiroute(int argc, char **argv)
273*de1e4e89SAndroid Build Coastguard Worker {
274*de1e4e89SAndroid Build Coastguard Worker if (argc < 1)
275*de1e4e89SAndroid Build Coastguard Worker return mroute_list(0, NULL);
276*de1e4e89SAndroid Build Coastguard Worker #if 0
277*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "add") == 0)
278*de1e4e89SAndroid Build Coastguard Worker return mroute_modify(RTM_NEWADDR, argc-1, argv+1);
279*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "delete") == 0)
280*de1e4e89SAndroid Build Coastguard Worker return mroute_modify(RTM_DELADDR, argc-1, argv+1);
281*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "get") == 0)
282*de1e4e89SAndroid Build Coastguard Worker return mroute_get(argc-1, argv+1);
283*de1e4e89SAndroid Build Coastguard Worker #endif
284*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0
285*de1e4e89SAndroid Build Coastguard Worker || matches(*argv, "lst") == 0)
286*de1e4e89SAndroid Build Coastguard Worker return mroute_list(argc-1, argv+1);
287*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "help") == 0)
288*de1e4e89SAndroid Build Coastguard Worker usage();
289*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Command \"%s\" is unknown, try \"ip mroute help\".\n", *argv);
290*de1e4e89SAndroid Build Coastguard Worker exit(-1);
291*de1e4e89SAndroid Build Coastguard Worker }
292