1*4dc78e53SAndroid Build Coastguard Worker /* SPDX-License-Identifier: LGPL-2.1-only */
2*4dc78e53SAndroid Build Coastguard Worker /*
3*4dc78e53SAndroid Build Coastguard Worker * Copyright (c) 2008-2009 Thomas Graf <[email protected]>
4*4dc78e53SAndroid Build Coastguard Worker */
5*4dc78e53SAndroid Build Coastguard Worker
6*4dc78e53SAndroid Build Coastguard Worker /**
7*4dc78e53SAndroid Build Coastguard Worker * @ingroup cli
8*4dc78e53SAndroid Build Coastguard Worker * @defgroup cli_route Routing
9*4dc78e53SAndroid Build Coastguard Worker *
10*4dc78e53SAndroid Build Coastguard Worker * @{
11*4dc78e53SAndroid Build Coastguard Worker */
12*4dc78e53SAndroid Build Coastguard Worker
13*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
14*4dc78e53SAndroid Build Coastguard Worker
15*4dc78e53SAndroid Build Coastguard Worker #include <netlink/cli/utils.h>
16*4dc78e53SAndroid Build Coastguard Worker #include <netlink/cli/route.h>
17*4dc78e53SAndroid Build Coastguard Worker
nl_cli_route_alloc(void)18*4dc78e53SAndroid Build Coastguard Worker struct rtnl_route *nl_cli_route_alloc(void)
19*4dc78e53SAndroid Build Coastguard Worker {
20*4dc78e53SAndroid Build Coastguard Worker struct rtnl_route *route;
21*4dc78e53SAndroid Build Coastguard Worker
22*4dc78e53SAndroid Build Coastguard Worker route = rtnl_route_alloc();
23*4dc78e53SAndroid Build Coastguard Worker if (!route)
24*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(ENOMEM, "Unable to allocate route object");
25*4dc78e53SAndroid Build Coastguard Worker
26*4dc78e53SAndroid Build Coastguard Worker return route;
27*4dc78e53SAndroid Build Coastguard Worker }
28*4dc78e53SAndroid Build Coastguard Worker
nl_cli_route_alloc_cache(struct nl_sock * sk,int flags)29*4dc78e53SAndroid Build Coastguard Worker struct nl_cache *nl_cli_route_alloc_cache(struct nl_sock *sk, int flags)
30*4dc78e53SAndroid Build Coastguard Worker {
31*4dc78e53SAndroid Build Coastguard Worker struct nl_cache *cache;
32*4dc78e53SAndroid Build Coastguard Worker int err;
33*4dc78e53SAndroid Build Coastguard Worker
34*4dc78e53SAndroid Build Coastguard Worker if ((err = rtnl_route_alloc_cache(sk, AF_UNSPEC, flags, &cache)) < 0)
35*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(err, "Unable to allocate route cache: %s\n",
36*4dc78e53SAndroid Build Coastguard Worker nl_geterror(err));
37*4dc78e53SAndroid Build Coastguard Worker
38*4dc78e53SAndroid Build Coastguard Worker nl_cache_mngt_provide(cache);
39*4dc78e53SAndroid Build Coastguard Worker
40*4dc78e53SAndroid Build Coastguard Worker return cache;
41*4dc78e53SAndroid Build Coastguard Worker }
42*4dc78e53SAndroid Build Coastguard Worker
nl_cli_route_parse_family(struct rtnl_route * route,char * arg)43*4dc78e53SAndroid Build Coastguard Worker void nl_cli_route_parse_family(struct rtnl_route *route, char *arg)
44*4dc78e53SAndroid Build Coastguard Worker {
45*4dc78e53SAndroid Build Coastguard Worker int family;
46*4dc78e53SAndroid Build Coastguard Worker
47*4dc78e53SAndroid Build Coastguard Worker if ((family = nl_str2af(arg)) != AF_UNSPEC)
48*4dc78e53SAndroid Build Coastguard Worker rtnl_route_set_family(route, family);
49*4dc78e53SAndroid Build Coastguard Worker }
50*4dc78e53SAndroid Build Coastguard Worker
nl_cli_route_parse_dst(struct rtnl_route * route,char * arg)51*4dc78e53SAndroid Build Coastguard Worker void nl_cli_route_parse_dst(struct rtnl_route *route, char *arg)
52*4dc78e53SAndroid Build Coastguard Worker {
53*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *addr;
54*4dc78e53SAndroid Build Coastguard Worker int err;
55*4dc78e53SAndroid Build Coastguard Worker
56*4dc78e53SAndroid Build Coastguard Worker addr = nl_cli_addr_parse(arg, rtnl_route_get_family(route));
57*4dc78e53SAndroid Build Coastguard Worker if ((err = rtnl_route_set_dst(route, addr)) < 0)
58*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(err, "Unable to set destination address: %s",
59*4dc78e53SAndroid Build Coastguard Worker nl_geterror(err));
60*4dc78e53SAndroid Build Coastguard Worker
61*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(addr);
62*4dc78e53SAndroid Build Coastguard Worker }
63*4dc78e53SAndroid Build Coastguard Worker
nl_cli_route_parse_src(struct rtnl_route * route,char * arg)64*4dc78e53SAndroid Build Coastguard Worker void nl_cli_route_parse_src(struct rtnl_route *route, char *arg)
65*4dc78e53SAndroid Build Coastguard Worker {
66*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *addr;
67*4dc78e53SAndroid Build Coastguard Worker int err;
68*4dc78e53SAndroid Build Coastguard Worker
69*4dc78e53SAndroid Build Coastguard Worker addr = nl_cli_addr_parse(arg, rtnl_route_get_family(route));
70*4dc78e53SAndroid Build Coastguard Worker if ((err = rtnl_route_set_src(route, addr)) < 0)
71*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(err, "Unable to set source address: %s",
72*4dc78e53SAndroid Build Coastguard Worker nl_geterror(err));
73*4dc78e53SAndroid Build Coastguard Worker
74*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(addr);
75*4dc78e53SAndroid Build Coastguard Worker }
76*4dc78e53SAndroid Build Coastguard Worker
nl_cli_route_parse_pref_src(struct rtnl_route * route,char * arg)77*4dc78e53SAndroid Build Coastguard Worker void nl_cli_route_parse_pref_src(struct rtnl_route *route, char *arg)
78*4dc78e53SAndroid Build Coastguard Worker {
79*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *addr;
80*4dc78e53SAndroid Build Coastguard Worker int err;
81*4dc78e53SAndroid Build Coastguard Worker
82*4dc78e53SAndroid Build Coastguard Worker addr = nl_cli_addr_parse(arg, rtnl_route_get_family(route));
83*4dc78e53SAndroid Build Coastguard Worker if ((err = rtnl_route_set_pref_src(route, addr)) < 0)
84*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(err, "Unable to set preferred source address: %s",
85*4dc78e53SAndroid Build Coastguard Worker nl_geterror(err));
86*4dc78e53SAndroid Build Coastguard Worker
87*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(addr);
88*4dc78e53SAndroid Build Coastguard Worker }
89*4dc78e53SAndroid Build Coastguard Worker
nl_cli_route_parse_metric(struct rtnl_route * route,char * subopts)90*4dc78e53SAndroid Build Coastguard Worker void nl_cli_route_parse_metric(struct rtnl_route *route, char *subopts)
91*4dc78e53SAndroid Build Coastguard Worker {
92*4dc78e53SAndroid Build Coastguard Worker /* strict equal order to RTAX_* */
93*4dc78e53SAndroid Build Coastguard Worker static char *const tokens[] = {
94*4dc78e53SAndroid Build Coastguard Worker "unspec",
95*4dc78e53SAndroid Build Coastguard Worker "lock",
96*4dc78e53SAndroid Build Coastguard Worker "mtu",
97*4dc78e53SAndroid Build Coastguard Worker "window",
98*4dc78e53SAndroid Build Coastguard Worker "rtt",
99*4dc78e53SAndroid Build Coastguard Worker "rttvar",
100*4dc78e53SAndroid Build Coastguard Worker "sstresh",
101*4dc78e53SAndroid Build Coastguard Worker "cwnd",
102*4dc78e53SAndroid Build Coastguard Worker "advmss",
103*4dc78e53SAndroid Build Coastguard Worker "reordering",
104*4dc78e53SAndroid Build Coastguard Worker "hoplimit",
105*4dc78e53SAndroid Build Coastguard Worker "initcwnd",
106*4dc78e53SAndroid Build Coastguard Worker "features",
107*4dc78e53SAndroid Build Coastguard Worker NULL,
108*4dc78e53SAndroid Build Coastguard Worker };
109*4dc78e53SAndroid Build Coastguard Worker unsigned long lval;
110*4dc78e53SAndroid Build Coastguard Worker char *arg, *endptr;
111*4dc78e53SAndroid Build Coastguard Worker
112*4dc78e53SAndroid Build Coastguard Worker while (*subopts != '\0') {
113*4dc78e53SAndroid Build Coastguard Worker int ret = getsubopt(&subopts, tokens, &arg);
114*4dc78e53SAndroid Build Coastguard Worker if (ret == -1)
115*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(EINVAL, "Unknown metric token \"%s\"", arg);
116*4dc78e53SAndroid Build Coastguard Worker
117*4dc78e53SAndroid Build Coastguard Worker if (ret == 0)
118*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(EINVAL, "Invalid metric \"%s\"", tokens[ret]);
119*4dc78e53SAndroid Build Coastguard Worker
120*4dc78e53SAndroid Build Coastguard Worker if (arg == NULL)
121*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(EINVAL, "Metric \"%s\", no value given", tokens[ret]);
122*4dc78e53SAndroid Build Coastguard Worker
123*4dc78e53SAndroid Build Coastguard Worker lval = strtoul(arg, &endptr, 0);
124*4dc78e53SAndroid Build Coastguard Worker if (endptr == arg)
125*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(EINVAL, "Metric \"%s\", value not numeric", tokens[ret]);
126*4dc78e53SAndroid Build Coastguard Worker
127*4dc78e53SAndroid Build Coastguard Worker if ((ret = rtnl_route_set_metric(route, ret, lval)) < 0)
128*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(ret, "Unable to set metric: %s",
129*4dc78e53SAndroid Build Coastguard Worker nl_geterror(ret));
130*4dc78e53SAndroid Build Coastguard Worker }
131*4dc78e53SAndroid Build Coastguard Worker }
132*4dc78e53SAndroid Build Coastguard Worker
nl_cli_route_parse_nexthop(struct rtnl_route * route,char * subopts,struct nl_cache * link_cache)133*4dc78e53SAndroid Build Coastguard Worker void nl_cli_route_parse_nexthop(struct rtnl_route *route, char *subopts,
134*4dc78e53SAndroid Build Coastguard Worker struct nl_cache *link_cache)
135*4dc78e53SAndroid Build Coastguard Worker {
136*4dc78e53SAndroid Build Coastguard Worker enum {
137*4dc78e53SAndroid Build Coastguard Worker NH_DEV,
138*4dc78e53SAndroid Build Coastguard Worker NH_VIA,
139*4dc78e53SAndroid Build Coastguard Worker NH_WEIGHT,
140*4dc78e53SAndroid Build Coastguard Worker NH_AS,
141*4dc78e53SAndroid Build Coastguard Worker };
142*4dc78e53SAndroid Build Coastguard Worker static char *const tokens[] = {
143*4dc78e53SAndroid Build Coastguard Worker "dev",
144*4dc78e53SAndroid Build Coastguard Worker "via",
145*4dc78e53SAndroid Build Coastguard Worker "weight",
146*4dc78e53SAndroid Build Coastguard Worker "as",
147*4dc78e53SAndroid Build Coastguard Worker NULL,
148*4dc78e53SAndroid Build Coastguard Worker };
149*4dc78e53SAndroid Build Coastguard Worker struct rtnl_nexthop *nh;
150*4dc78e53SAndroid Build Coastguard Worker unsigned long lval;
151*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *addr;
152*4dc78e53SAndroid Build Coastguard Worker int ival;
153*4dc78e53SAndroid Build Coastguard Worker char *arg, *endptr;
154*4dc78e53SAndroid Build Coastguard Worker
155*4dc78e53SAndroid Build Coastguard Worker if (!(nh = rtnl_route_nh_alloc()))
156*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(ENOMEM, "Out of memory");
157*4dc78e53SAndroid Build Coastguard Worker
158*4dc78e53SAndroid Build Coastguard Worker while (*subopts != '\0') {
159*4dc78e53SAndroid Build Coastguard Worker int ret = getsubopt(&subopts, tokens, &arg);
160*4dc78e53SAndroid Build Coastguard Worker if (ret == -1)
161*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(EINVAL, "Unknown nexthop token \"%s\"", arg);
162*4dc78e53SAndroid Build Coastguard Worker
163*4dc78e53SAndroid Build Coastguard Worker if (arg == NULL)
164*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(EINVAL, "Missing argument to option \"%s\"\n",
165*4dc78e53SAndroid Build Coastguard Worker tokens[ret]);
166*4dc78e53SAndroid Build Coastguard Worker
167*4dc78e53SAndroid Build Coastguard Worker switch (ret) {
168*4dc78e53SAndroid Build Coastguard Worker case NH_DEV:
169*4dc78e53SAndroid Build Coastguard Worker if (!(ival = rtnl_link_name2i(link_cache, arg)))
170*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(ENOENT,"Link \"%s\" does not exist", arg);
171*4dc78e53SAndroid Build Coastguard Worker
172*4dc78e53SAndroid Build Coastguard Worker rtnl_route_nh_set_ifindex(nh, ival);
173*4dc78e53SAndroid Build Coastguard Worker break;
174*4dc78e53SAndroid Build Coastguard Worker
175*4dc78e53SAndroid Build Coastguard Worker case NH_VIA:
176*4dc78e53SAndroid Build Coastguard Worker if (rtnl_route_get_family(route) == AF_MPLS) {
177*4dc78e53SAndroid Build Coastguard Worker addr = nl_cli_addr_parse(arg, 0);
178*4dc78e53SAndroid Build Coastguard Worker rtnl_route_nh_set_via(nh, addr);
179*4dc78e53SAndroid Build Coastguard Worker } else {
180*4dc78e53SAndroid Build Coastguard Worker addr = nl_cli_addr_parse(arg,rtnl_route_get_family(route));
181*4dc78e53SAndroid Build Coastguard Worker rtnl_route_nh_set_gateway(nh, addr);
182*4dc78e53SAndroid Build Coastguard Worker }
183*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(addr);
184*4dc78e53SAndroid Build Coastguard Worker break;
185*4dc78e53SAndroid Build Coastguard Worker
186*4dc78e53SAndroid Build Coastguard Worker case NH_AS:
187*4dc78e53SAndroid Build Coastguard Worker addr = nl_cli_addr_parse(arg,
188*4dc78e53SAndroid Build Coastguard Worker rtnl_route_get_family(route));
189*4dc78e53SAndroid Build Coastguard Worker rtnl_route_nh_set_newdst(nh, addr);
190*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(addr);
191*4dc78e53SAndroid Build Coastguard Worker break;
192*4dc78e53SAndroid Build Coastguard Worker
193*4dc78e53SAndroid Build Coastguard Worker case NH_WEIGHT:
194*4dc78e53SAndroid Build Coastguard Worker lval = strtoul(arg, &endptr, 0);
195*4dc78e53SAndroid Build Coastguard Worker if (endptr == arg)
196*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(EINVAL,
197*4dc78e53SAndroid Build Coastguard Worker "Invalid weight \"%s\", not numeric",
198*4dc78e53SAndroid Build Coastguard Worker arg);
199*4dc78e53SAndroid Build Coastguard Worker rtnl_route_nh_set_weight(nh, lval);
200*4dc78e53SAndroid Build Coastguard Worker break;
201*4dc78e53SAndroid Build Coastguard Worker }
202*4dc78e53SAndroid Build Coastguard Worker }
203*4dc78e53SAndroid Build Coastguard Worker
204*4dc78e53SAndroid Build Coastguard Worker rtnl_route_add_nexthop(route, nh);
205*4dc78e53SAndroid Build Coastguard Worker }
206*4dc78e53SAndroid Build Coastguard Worker
nl_cli_route_parse_table(struct rtnl_route * route,char * arg)207*4dc78e53SAndroid Build Coastguard Worker void nl_cli_route_parse_table(struct rtnl_route *route, char *arg)
208*4dc78e53SAndroid Build Coastguard Worker {
209*4dc78e53SAndroid Build Coastguard Worker unsigned long lval;
210*4dc78e53SAndroid Build Coastguard Worker char *endptr;
211*4dc78e53SAndroid Build Coastguard Worker int table;
212*4dc78e53SAndroid Build Coastguard Worker
213*4dc78e53SAndroid Build Coastguard Worker lval = strtoul(arg, &endptr, 0);
214*4dc78e53SAndroid Build Coastguard Worker if (endptr == arg) {
215*4dc78e53SAndroid Build Coastguard Worker if ((table = rtnl_route_str2table(arg)) < 0)
216*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(EINVAL, "Unknown table name \"%s\"", arg);
217*4dc78e53SAndroid Build Coastguard Worker }
218*4dc78e53SAndroid Build Coastguard Worker else {
219*4dc78e53SAndroid Build Coastguard Worker table = lval;
220*4dc78e53SAndroid Build Coastguard Worker }
221*4dc78e53SAndroid Build Coastguard Worker
222*4dc78e53SAndroid Build Coastguard Worker rtnl_route_set_table(route, table);
223*4dc78e53SAndroid Build Coastguard Worker }
224*4dc78e53SAndroid Build Coastguard Worker
nl_cli_route_parse_prio(struct rtnl_route * route,char * arg)225*4dc78e53SAndroid Build Coastguard Worker void nl_cli_route_parse_prio(struct rtnl_route *route, char *arg)
226*4dc78e53SAndroid Build Coastguard Worker {
227*4dc78e53SAndroid Build Coastguard Worker unsigned long lval;
228*4dc78e53SAndroid Build Coastguard Worker char *endptr;
229*4dc78e53SAndroid Build Coastguard Worker
230*4dc78e53SAndroid Build Coastguard Worker lval = strtoul(arg, &endptr, 0);
231*4dc78e53SAndroid Build Coastguard Worker if (endptr == arg)
232*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(EINVAL, "Invalid priority value, not numeric");
233*4dc78e53SAndroid Build Coastguard Worker rtnl_route_set_priority(route, lval);
234*4dc78e53SAndroid Build Coastguard Worker }
235*4dc78e53SAndroid Build Coastguard Worker
nl_cli_route_parse_scope(struct rtnl_route * route,char * arg)236*4dc78e53SAndroid Build Coastguard Worker void nl_cli_route_parse_scope(struct rtnl_route *route, char *arg)
237*4dc78e53SAndroid Build Coastguard Worker {
238*4dc78e53SAndroid Build Coastguard Worker int ival;
239*4dc78e53SAndroid Build Coastguard Worker
240*4dc78e53SAndroid Build Coastguard Worker if ((ival = rtnl_str2scope(arg)) < 0)
241*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(EINVAL, "Unknown routing scope \"%s\"", arg);
242*4dc78e53SAndroid Build Coastguard Worker
243*4dc78e53SAndroid Build Coastguard Worker rtnl_route_set_scope(route, ival);
244*4dc78e53SAndroid Build Coastguard Worker }
245*4dc78e53SAndroid Build Coastguard Worker
nl_cli_route_parse_protocol(struct rtnl_route * route,char * arg)246*4dc78e53SAndroid Build Coastguard Worker void nl_cli_route_parse_protocol(struct rtnl_route *route, char *arg)
247*4dc78e53SAndroid Build Coastguard Worker {
248*4dc78e53SAndroid Build Coastguard Worker unsigned long lval;
249*4dc78e53SAndroid Build Coastguard Worker char *endptr;
250*4dc78e53SAndroid Build Coastguard Worker int proto;
251*4dc78e53SAndroid Build Coastguard Worker
252*4dc78e53SAndroid Build Coastguard Worker lval = strtoul(arg, &endptr, 0);
253*4dc78e53SAndroid Build Coastguard Worker if (endptr == arg) {
254*4dc78e53SAndroid Build Coastguard Worker if ((proto = rtnl_route_str2proto(arg)) < 0)
255*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(EINVAL,
256*4dc78e53SAndroid Build Coastguard Worker "Unknown routing protocol name \"%s\"",
257*4dc78e53SAndroid Build Coastguard Worker arg);
258*4dc78e53SAndroid Build Coastguard Worker }
259*4dc78e53SAndroid Build Coastguard Worker else {
260*4dc78e53SAndroid Build Coastguard Worker proto = lval;
261*4dc78e53SAndroid Build Coastguard Worker }
262*4dc78e53SAndroid Build Coastguard Worker
263*4dc78e53SAndroid Build Coastguard Worker rtnl_route_set_protocol(route, proto);
264*4dc78e53SAndroid Build Coastguard Worker }
265*4dc78e53SAndroid Build Coastguard Worker
nl_cli_route_parse_type(struct rtnl_route * route,char * arg)266*4dc78e53SAndroid Build Coastguard Worker void nl_cli_route_parse_type(struct rtnl_route *route, char *arg)
267*4dc78e53SAndroid Build Coastguard Worker {
268*4dc78e53SAndroid Build Coastguard Worker int ival;
269*4dc78e53SAndroid Build Coastguard Worker
270*4dc78e53SAndroid Build Coastguard Worker if ((ival = nl_str2rtntype(arg)) < 0)
271*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(EINVAL, "Unknown routing type \"%s\"", arg);
272*4dc78e53SAndroid Build Coastguard Worker
273*4dc78e53SAndroid Build Coastguard Worker if ((ival = rtnl_route_set_type(route, ival)) < 0)
274*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(ival, "Unable to set routing type: %s",
275*4dc78e53SAndroid Build Coastguard Worker nl_geterror(ival));
276*4dc78e53SAndroid Build Coastguard Worker }
277*4dc78e53SAndroid Build Coastguard Worker
nl_cli_route_parse_iif(struct rtnl_route * route,char * arg,struct nl_cache * link_cache)278*4dc78e53SAndroid Build Coastguard Worker void nl_cli_route_parse_iif(struct rtnl_route *route, char *arg, struct nl_cache *link_cache)
279*4dc78e53SAndroid Build Coastguard Worker {
280*4dc78e53SAndroid Build Coastguard Worker int ival;
281*4dc78e53SAndroid Build Coastguard Worker
282*4dc78e53SAndroid Build Coastguard Worker if (!(ival = rtnl_link_name2i(link_cache, arg)))
283*4dc78e53SAndroid Build Coastguard Worker nl_cli_fatal(ENOENT, "Link \"%s\" does not exist", arg);
284*4dc78e53SAndroid Build Coastguard Worker
285*4dc78e53SAndroid Build Coastguard Worker rtnl_route_set_iif(route, ival);
286*4dc78e53SAndroid Build Coastguard Worker }
287*4dc78e53SAndroid Build Coastguard Worker
288*4dc78e53SAndroid Build Coastguard Worker /** @} */
289