aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--toys/pending/route.c85
1 files changed, 48 insertions, 37 deletions
diff --git a/toys/pending/route.c b/toys/pending/route.c
index dd7dfc3b..3a00687d 100644
--- a/toys/pending/route.c
+++ b/toys/pending/route.c
@@ -5,20 +5,45 @@
*
* No Standard
*
+ * TODO: autodetect -net -host target dev -A (but complain)
+ * route add -net target 10.0.0.0 netmask 255.0.0.0 dev eth0
+ * route del delete
+ * delete net route, must match netmask, informative error message
+ *
+ * mod dyn reinstate metric netmask gw mss window irtt dev
+
USE_ROUTE(NEWTOY(route, "?neA:", TOYFLAG_BIN))
config ROUTE
bool "route"
default n
help
- usage: route [-ne] [-A inet[6]] / [add|del]
+ usage: route [-ne] [-A [46]] [add|del TARGET [OPTIONS]]
+
+ Display, add or delete network routes in the "Forwarding Information Base".
+
+ -n Show numerical addresses (no DNS lookups)
+ -e display netstat fields
+
+ Routing means sending packets out a network interface to an address.
+ The kernel can tell where to send packets one hop away by examining each
+ interface's address and netmask, so the most common use of this command
+ is to identify a "gateway" that forwards other traffic.
- Display/Edit kernel routing tables.
+ Assigning an address to an interface automatically creates an appropriate
+ network route ("ifconfig eth0 10.0.2.15/8" does "route add 10.0.0.0/8 eth0"
+ for you), although some devices (such as loopback) won't show it in the
+ table. For machines more than one hop away, you need to specify a gateway
+ (ala "route add default gw 10.0.2.2").
- -n no name lookups
- -e display other/more information
- -A inet{6} Select Address Family
+ The address "default" is a wildcard address (0.0.0.0/0) matching all
+ packets without a more specific route.
+
+ Available OPTIONS include:
+ reject - blocking route (force match failure)
+ dev NAME - force packets out this interface (ala "eth0")
+ netmask - old way of saying things like ADDR/24
+ gw ADDR - forward packets to gateway ADDR
- reject mod dyn reinstate metric netmask gw mss window irtt dev
*/
#define FOR_route
@@ -63,8 +88,9 @@ static int get_hostname(char *ipstr, struct sockaddr_in *sockin)
}
if (inet_aton(ipstr, &sockin->sin_addr)) return 0;
- if (!(host = gethostbyname(ipstr))) return -1;
+ if (!(host = gethostbyname(ipstr))) perror_exit("resolving '%s'", ipstr);
memcpy(&sockin->sin_addr, host->h_addr_list[0], sizeof(struct in_addr));
+
return 0;
}
@@ -160,24 +186,6 @@ static int get_action(char ***argv, struct _arglist *list)
}
/*
- * get prefix len (if any) and remove the prefix from target ip.
- * if no prefix then set netmask as default.
- */
-static void is_prefix(char **tip, char **netmask, struct rtentry *rt)
-{
- char *prefix = strchr(*tip, '/');
- if (prefix) {
- unsigned long plen;
- plen = atolx_range(prefix + 1, 0, 32);
- //used to verify the netmask and route conflict.
- (((struct sockaddr_in *)&((rt)->rt_genmask))->sin_addr.s_addr)
- = htonl( ~(INVALID_ADDR >> plen));
- *prefix = '\0';
- rt->rt_genmask.sa_family = AF_INET;
- } else *netmask = "default"; //default netmask.
-}
-
-/*
* used to get the params like: metric, netmask, gw, mss, window, irtt, dev and their values.
* additionally set the flag values for reject, mod, dyn and reinstate.
*/
@@ -201,22 +209,18 @@ static void get_next_params(char **argv, struct rtentry *rt, char **netmask)
if (addr_mask) help_exit("dup netmask");
*netmask = *argv;
- if (get_hostname(*netmask, (struct sockaddr_in *) &sock) < 0)
- perror_exit("resolving '%s'", *netmask);
+ get_hostname(*netmask, (struct sockaddr_in *) &sock);
rt->rt_genmask = sock;
} else if (!strcmp(*argv, "gw")) {
//route packets via a gateway.
if (!(rt->rt_flags & RTF_GATEWAY)) {
- int ishost;
-
- if ((ishost = get_hostname(*argv, (struct sockaddr_in *) &rt->rt_gateway)) == 0) {
+ if (!get_hostname(*argv, (struct sockaddr_in *) &rt->rt_gateway))
rt->rt_flags |= RTF_GATEWAY;
- } else if (ishost < 0) perror_exit("resolving '%s'", *argv);
else perror_exit("gateway '%s' is a NETWORK", *argv);
} else help_exit("dup gw");
} else if (!strcmp(*argv, "mss")) {
//set the TCP Maximum Segment Size for connections over this route.
- rt->rt_mss = atolx_range(*argv, 64, 32768); //MSS low and max
+ rt->rt_mtu = atolx_range(*argv, 64, 65536);
rt->rt_flags |= RTF_MSS;
} else if (!strcmp(*argv, "window")) {
//set the TCP window size for connections over this route to W bytes.
@@ -253,7 +257,7 @@ static void verify_netmask(struct rtentry *rt, char *netmask)
static void setroute(char **argv)
{
struct rtentry rt;
- char *netmask = NULL, *targetip;
+ char *netmask, *targetip;
int is_net_or_host = 0, sokfd, arg2_action;
int action = get_action(&argv, arglist1); //verify the arg for add/del.
@@ -265,10 +269,17 @@ static void setroute(char **argv)
memset(&rt, 0, sizeof(struct rtentry));
targetip = *argv++;
- is_prefix((char **)&targetip, (char **)&netmask, &rt);
- if ((is_net_or_host = get_hostname(targetip,
- (struct sockaddr_in *) &rt.rt_dst)) < 0)
- perror_exit("resolving '%s'", targetip);
+ netmask = strchr(targetip, '/');
+ if (netmask) {
+ *netmask++ = 0;
+ //used to verify the netmask and route conflict.
+ (((struct sockaddr_in *)&rt.rt_genmask)->sin_addr.s_addr)
+ = htonl((1<<(32-atolx_range(netmask, 0, 32)))-1);
+ rt.rt_genmask.sa_family = AF_INET;
+ netmask = 0;
+ } else netmask = "default";
+
+ is_net_or_host = get_hostname(targetip, (void *)&rt.rt_dst);
if (arg2_action) is_net_or_host = arg2_action & 1;
rt.rt_flags = ((is_net_or_host) ? RTF_UP : (RTF_UP | RTF_HOST));