libnl 3.11.0
route.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2008-2009 Thomas Graf <tgraf@suug.ch>
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
18struct 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
29struct 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
39
40 return cache;
41}
42
43void 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
51void 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
64void 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
77void 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
90void 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
133void 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
207void 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
225void 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
236void 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
246void 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
266void 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
278void 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/** @} */
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
Definition addr.c:541
void nl_cache_mngt_provide(struct nl_cache *cache)
Provide a cache for global use.
Definition cache_mngt.c:332
void nl_cli_fatal(int err, const char *fmt,...)
Print error message and quit application.
Definition utils.c:71
int rtnl_route_alloc_cache(struct nl_sock *sk, int family, int flags, struct nl_cache **result)
Build a route cache holding all routes currently configured in the kernel.
Definition route.c:80