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