Tizen 2.1 base
[platform/upstream/libnl2.git] / src / lib / route.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 /** @} */