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