• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 	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 
nl_cli_route_parse_prio(struct rtnl_route * route,char * arg)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 
nl_cli_route_parse_scope(struct rtnl_route * route,char * arg)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 
nl_cli_route_parse_protocol(struct rtnl_route * route,char * arg)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 
nl_cli_route_parse_type(struct rtnl_route * route,char * arg)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 
nl_cli_route_parse_iif(struct rtnl_route * route,char * arg,struct nl_cache * link_cache)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 /** @} */
279