libnl  3.2.24-rc1
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  };
145  static char *const tokens[] = {
146  "dev",
147  "via",
148  "weight",
149  NULL,
150  };
151  struct rtnl_nexthop *nh;
152  unsigned long lval;
153  struct nl_addr *addr;
154  int ival;
155  char *arg, *endptr;
156 
157  if (!(nh = rtnl_route_nh_alloc()))
158  nl_cli_fatal(ENOMEM, "Out of memory");
159 
160  while (*subopts != '\0') {
161  int ret = getsubopt(&subopts, tokens, &arg);
162  if (ret == -1)
163  nl_cli_fatal(EINVAL, "Unknown nexthop token \"%s\"", arg);
164 
165  if (arg == NULL)
166  nl_cli_fatal(EINVAL, "Missing argument to option \"%s\"\n",
167  tokens[ret]);
168 
169  switch (ret) {
170  case NH_DEV:
171  if (!(ival = rtnl_link_name2i(link_cache, arg)))
172  nl_cli_fatal(ENOENT,"Link \"%s\" does not exist", arg);
173 
174  rtnl_route_nh_set_ifindex(nh, ival);
175  break;
176 
177  case NH_VIA:
178  addr = nl_cli_addr_parse(arg,rtnl_route_get_family(route));
179  rtnl_route_nh_set_gateway(nh, addr);
180  nl_addr_put(addr);
181  break;
182 
183  case NH_WEIGHT:
184  lval = strtoul(arg, &endptr, 0);
185  if (endptr == arg)
186  nl_cli_fatal(EINVAL,
187  "Invalid weight \"%s\", not numeric",
188  arg);
189  rtnl_route_nh_set_weight(nh, lval);
190  break;
191  }
192  }
193 
194  rtnl_route_add_nexthop(route, nh);
195 }
196 
197 void nl_cli_route_parse_table(struct rtnl_route *route, char *arg)
198 {
199  unsigned long lval;
200  char *endptr;
201  int table;
202 
203  lval = strtoul(arg, &endptr, 0);
204  if (endptr == arg) {
205  if ((table = rtnl_route_str2table(arg)) < 0)
206  nl_cli_fatal(EINVAL, "Unknown table name \"%s\"", arg);
207  }
208  else {
209  table = lval;
210  }
211 
212  rtnl_route_set_table(route, table);
213 }
214 
215 void nl_cli_route_parse_prio(struct rtnl_route *route, char *arg)
216 {
217  unsigned long lval;
218  char *endptr;
219 
220  lval = strtoul(arg, &endptr, 0);
221  if (endptr == arg)
222  nl_cli_fatal(EINVAL, "Invalid priority value, not numeric");
223  rtnl_route_set_priority(route, lval);
224 }
225 
226 void nl_cli_route_parse_scope(struct rtnl_route *route, char *arg)
227 {
228  int ival;
229 
230  if ((ival = rtnl_str2scope(arg)) < 0)
231  nl_cli_fatal(EINVAL, "Unknown routing scope \"%s\"", arg);
232 
233  rtnl_route_set_scope(route, ival);
234 }
235 
236 void nl_cli_route_parse_protocol(struct rtnl_route *route, char *arg)
237 {
238  unsigned long lval;
239  char *endptr;
240  int proto;
241 
242  lval = strtoul(arg, &endptr, 0);
243  if (endptr == arg) {
244  if ((proto = rtnl_route_str2proto(arg)) < 0)
245  nl_cli_fatal(EINVAL,
246  "Unknown routing protocol name \"%s\"",
247  arg);
248  }
249  else {
250  proto = lval;
251  }
252 
253  rtnl_route_set_protocol(route, proto);
254 }
255 
256 void nl_cli_route_parse_type(struct rtnl_route *route, char *arg)
257 {
258  int ival;
259 
260  if ((ival = nl_str2rtntype(arg)) < 0)
261  nl_cli_fatal(EINVAL, "Unknown routing type \"%s\"", arg);
262 
263  if ((ival = rtnl_route_set_type(route, ival)) < 0)
264  nl_cli_fatal(ival, "Unable to set routing type: %s",
265  nl_geterror(ival));
266 }
267 
268 void nl_cli_route_parse_iif(struct rtnl_route *route, char *arg, struct nl_cache *link_cache)
269 {
270  int ival;
271 
272  if (!(ival = rtnl_link_name2i(link_cache, arg)))
273  nl_cli_fatal(ENOENT, "Link \"%s\" does not exist", arg);
274 
275  rtnl_route_set_iif(route, ival);
276 }
277 
278 /** @} */