diff --git a/toolbox/route.c b/toolbox/route.c index 2fd71080c..4f66201b0 100644 --- a/toolbox/route.c +++ b/toolbox/route.c @@ -1,130 +1,103 @@ +/* + * Copyright (c) 2009, The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google, Inc. nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ #include -#include -#include -#include - -#include #include -#include - +#include +#include +#include #include #include -#include -#include #include #include -static void die(const char *fmt, ...) -{ - va_list p; - - va_start(p, fmt); - fprintf(stderr,"error(%s): ", strerror(errno)); - fprintf(stderr, fmt, p); - va_end(p); - exit(-1); +static inline int set_address(const char *address, struct sockaddr *sa) { + return inet_aton(address, &((struct sockaddr_in *)sa)->sin_addr); } -static inline void init_sockaddr_in(struct sockaddr_in *sin, const char *addr) -{ - sin->sin_family = AF_INET; - sin->sin_port = 0; - sin->sin_addr.s_addr = inet_addr(addr); -} - -#define ADVANCE(argc, argv) do { argc--, argv++; } while(0) -#define EXPECT_NEXT(argc, argv) do { \ - ADVANCE(argc, argv); \ - if (0 == argc) { \ - errno = EINVAL; \ - die("expecting one more argument"); \ - } \ -} while(0) - /* current support the following routing entries */ /* route add default dev wlan0 */ -/* route add default gw 192.168.20.1 dev wlan0 */ -/* route add net 192.168.1.1 netmask 255.255.255.0 gw 172.24.192.10 */ +/* route add default gw 192.168.1.1 dev wlan0 */ +/* route add -net 192.168.1.2 netmask 255.255.255.0 gw 192.168.1.1 */ int route_main(int argc, char *argv[]) { - struct ifreq ifr; - int s,i; - struct rtentry rt; - struct sockaddr_in ina; - - if (!argc) - return 0; + struct rtentry rt = { + .rt_dst = {.sa_family = AF_INET}, + .rt_genmask = {.sa_family = AF_INET}, + .rt_gateway = {.sa_family = AF_INET}, + }; - strncpy(ifr.ifr_name, argv[0], IFNAMSIZ); - ifr.ifr_name[IFNAMSIZ-1] = 0; - ADVANCE(argc, argv); + errno = EINVAL; + if (argc > 2 && !strcmp(argv[1], "add")) { + if (!strcmp(argv[2], "default")) { + /* route add default dev wlan0 */ + if (argc > 4 && !strcmp(argv[3], "dev")) { + rt.rt_flags = RTF_UP | RTF_HOST; + rt.rt_dev = argv[4]; + errno = 0; + goto apply; + } - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - die("cannot open control socket\n"); - } - - while(argc > 0){ - if (!strcmp(argv[0], "add")) { - EXPECT_NEXT(argc, argv); - if (!strcmp(argv[0], "default")) { - EXPECT_NEXT(argc, argv); - memset((char *) &rt, 0, sizeof(struct rtentry)); - rt.rt_dst.sa_family = AF_INET; - if(!strcmp(argv[0], "dev")) { - EXPECT_NEXT(argc, argv); - rt.rt_flags = RTF_UP | RTF_HOST; - rt.rt_dev = argv[0]; - if (ioctl(s, SIOCADDRT, &rt) < 0) - die("SIOCADDRT\n"); - } else if (!strcmp(argv[0], "gw")) { - EXPECT_NEXT(argc, argv); - rt.rt_flags = RTF_UP | RTF_GATEWAY; - init_sockaddr_in((struct sockaddr_in *)&(rt.rt_genmask), "0.0.0.0"); - if(isdigit(argv[0][0])) { - init_sockaddr_in((struct sockaddr_in *)&(rt.rt_gateway), argv[0]); - } else { - die("expecting an IP address for parameter \"gw\"\n"); - } - EXPECT_NEXT(argc, argv); - if (!strcmp(argv[0], "dev")) { - EXPECT_NEXT(argc, argv); - rt.rt_dev = argv[0]; - if (ioctl(s, SIOCADDRT, &rt) < 0) { - die("SIOCADDRT\n"); - } - } - } - } else { - char keywords[3][10] = { "-net", "netmask", "gw" }; - struct sockaddr_in *paddr[3] = { &rt.rt_dst, &rt.rt_genmask, &rt.rt_gateway }; - int k = 0; - - memset((char *) &rt, 0, sizeof(struct rtentry)); + /* route add default gw 192.168.1.1 dev wlan0 */ + if (argc > 6 && !strcmp(argv[3], "gw") && !strcmp(argv[5], "dev")) { rt.rt_flags = RTF_UP | RTF_GATEWAY; - do { - if (!strcmp(argv[0], keywords[k])) { - EXPECT_NEXT(argc, argv); - if (isdigit(argv[0][0])) { - init_sockaddr_in(paddr[k], argv[0]); - } else { - die("expecting an IP/MASK address for parameter %s\n", keywords[k]); - } - if (k < 2) - EXPECT_NEXT(argc, argv); - } else { - die("expecting keyword(s)\n"); - } - } while (++k < 3); - - if (ioctl(s, SIOCADDRT, &rt) < 0) { - die("SIOCADDRT\n"); + rt.rt_dev = argv[6]; + if (set_address(argv[4], &rt.rt_gateway)) { + errno = 0; } + goto apply; } } - ADVANCE(argc, argv); + + /* route add -net 192.168.1.2 netmask 255.255.255.0 gw 192.168.1.1 */ + if (argc > 7 && !strcmp(argv[2], "-net") && + !strcmp(argv[4], "netmask") && !strcmp(argv[6], "gw")) { + rt.rt_flags = RTF_UP | RTF_GATEWAY; + if (set_address(argv[3], &rt.rt_dst) && + set_address(argv[5], &rt.rt_genmask) && + set_address(argv[7], &rt.rt_gateway)) { + errno = 0; + } + goto apply; + } } - return 0; +apply: + if (!errno) { + int s = socket(AF_INET, SOCK_DGRAM, 0); + if (s != -1 && (ioctl(s, SIOCADDRT, &rt) != -1 || errno == EEXIST)) { + return 0; + } + } + puts(strerror(errno)); + return errno; }