Home | History | Annotate | Download | only in lib
      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 (at) 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 	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 
    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 
    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 
    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 
    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 
    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