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