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
nl_cli_route_alloc(void)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
nl_cli_route_alloc_cache(struct nl_sock * sk,int flags)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
nl_cli_route_parse_family(struct rtnl_route * route,char * arg)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
nl_cli_route_parse_dst(struct rtnl_route * route,char * arg)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
nl_cli_route_parse_src(struct rtnl_route * route,char * arg)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
nl_cli_route_parse_pref_src(struct rtnl_route * route,char * arg)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
nl_cli_route_parse_metric(struct rtnl_route * route,char * subopts)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
nl_cli_route_parse_nexthop(struct rtnl_route * route,char * subopts,struct nl_cache * link_cache)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
nl_cli_route_parse_table(struct rtnl_route * route,char * arg)197 void nl_cli_route_parse_table(struct rtnl_route *route, char *arg)
198 {
199 unsigned long lval;
200 char *endptr;
201
202 lval = strtoul(arg, &endptr, 0);
203 if (endptr == arg) {
204 if ((lval = rtnl_route_str2table(arg)) < 0)
205 nl_cli_fatal(EINVAL, "Unknown table name \"%s\"", arg);
206 }
207
208 rtnl_route_set_table(route, lval);
209 }
210
nl_cli_route_parse_prio(struct rtnl_route * route,char * arg)211 void nl_cli_route_parse_prio(struct rtnl_route *route, char *arg)
212 {
213 unsigned long lval;
214 char *endptr;
215
216 lval = strtoul(arg, &endptr, 0);
217 if (endptr == arg)
218 nl_cli_fatal(EINVAL, "Invalid priority value, not numeric");
219 rtnl_route_set_priority(route, lval);
220 }
221
nl_cli_route_parse_scope(struct rtnl_route * route,char * arg)222 void nl_cli_route_parse_scope(struct rtnl_route *route, char *arg)
223 {
224 int ival;
225
226 if ((ival = rtnl_str2scope(arg)) < 0)
227 nl_cli_fatal(EINVAL, "Unknown routing scope \"%s\"", arg);
228
229 rtnl_route_set_scope(route, ival);
230 }
231
nl_cli_route_parse_protocol(struct rtnl_route * route,char * arg)232 void nl_cli_route_parse_protocol(struct rtnl_route *route, char *arg)
233 {
234 unsigned long lval;
235 char *endptr;
236
237 lval = strtoul(arg, &endptr, 0);
238 if (endptr == arg) {
239 if ((lval = rtnl_route_str2proto(arg)) < 0)
240 nl_cli_fatal(EINVAL,
241 "Unknown routing protocol name \"%s\"",
242 arg);
243 }
244
245 rtnl_route_set_protocol(route, lval);
246 }
247
nl_cli_route_parse_type(struct rtnl_route * route,char * arg)248 void nl_cli_route_parse_type(struct rtnl_route *route, char *arg)
249 {
250 int ival;
251
252 if ((ival = nl_str2rtntype(arg)) < 0)
253 nl_cli_fatal(EINVAL, "Unknown routing type \"%s\"", arg);
254
255 if ((ival = rtnl_route_set_type(route, ival)) < 0)
256 nl_cli_fatal(ival, "Unable to set routing type: %s",
257 nl_geterror(ival));
258 }
259
nl_cli_route_parse_iif(struct rtnl_route * route,char * arg,struct nl_cache * link_cache)260 void nl_cli_route_parse_iif(struct rtnl_route *route, char *arg, struct nl_cache *link_cache)
261 {
262 int ival;
263
264 if (!(ival = rtnl_link_name2i(link_cache, arg)))
265 nl_cli_fatal(ENOENT, "Link \"%s\" does not exist", arg);
266
267 rtnl_route_set_iif(route, ival);
268 }
269
270 /** @} */
271