• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
nl_cli_route_alloc(void)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 
nl_cli_route_alloc_cache(struct nl_sock * sk,int flags)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 
nl_cli_route_parse_family(struct rtnl_route * route,char * arg)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 
nl_cli_route_parse_dst(struct rtnl_route * route,char * arg)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 
nl_cli_route_parse_src(struct rtnl_route * route,char * arg)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 
nl_cli_route_parse_pref_src(struct rtnl_route * route,char * arg)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 
nl_cli_route_parse_metric(struct rtnl_route * route,char * subopts)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 
nl_cli_route_parse_nexthop(struct rtnl_route * route,char * subopts,struct nl_cache * link_cache)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 
nl_cli_route_parse_table(struct rtnl_route * route,char * arg)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 
nl_cli_route_parse_prio(struct rtnl_route * route,char * arg)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 
nl_cli_route_parse_scope(struct rtnl_route * route,char * arg)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 
nl_cli_route_parse_protocol(struct rtnl_route * route,char * arg)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 
nl_cli_route_parse_type(struct rtnl_route * route,char * arg)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 
nl_cli_route_parse_iif(struct rtnl_route * route,char * arg,struct nl_cache * link_cache)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 /** @} */
294