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