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