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