xref: /aosp_15_r20/external/iproute2/ip/ipmroute.c (revision de1e4e894b0c224df933550f0afdecc354b238c4)
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