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 22struct 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 33struct 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 47void 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 55void 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 68void 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 81void 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 94void 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 137void 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 197void 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 211void 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 222void 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 232void 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 248void 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 260void 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/** @} */ 271