route.c revision 83ec181dc74d5dab4110e1895e62f1bdbf6d7d7a
1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h>
598c297f2448fd8194cae16d213dfc9194180fa3fChung-yih Wang#include <stdarg.h>
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <ctype.h>
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/socket.h>
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <netinet/in.h>
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/if.h>
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/sockios.h>
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <arpa/inet.h>
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/route.h>
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1898c297f2448fd8194cae16d213dfc9194180fa3fChung-yih Wangstatic void die(const char *fmt, ...)
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
2098c297f2448fd8194cae16d213dfc9194180fa3fChung-yih Wang    va_list p;
2198c297f2448fd8194cae16d213dfc9194180fa3fChung-yih Wang
2298c297f2448fd8194cae16d213dfc9194180fa3fChung-yih Wang    va_start(p, fmt);
2398c297f2448fd8194cae16d213dfc9194180fa3fChung-yih Wang    fprintf(stderr,"error(%s): ", strerror(errno));
2498c297f2448fd8194cae16d213dfc9194180fa3fChung-yih Wang    fprintf(stderr, fmt, p);
2598c297f2448fd8194cae16d213dfc9194180fa3fChung-yih Wang    va_end(p);
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    exit(-1);
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic inline void init_sockaddr_in(struct sockaddr_in *sin, const char *addr)
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	sin->sin_family = AF_INET;
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	sin->sin_port = 0;
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	sin->sin_addr.s_addr = inet_addr(addr);
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define ADVANCE(argc, argv) do { argc--, argv++; } while(0)
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define EXPECT_NEXT(argc, argv) do {        \
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ADVANCE(argc, argv);                    \
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (0 == argc) {  						\
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		errno = EINVAL;                     \
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		die("expecting one more argument"); \
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}                                       \
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} while(0)
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
4598c297f2448fd8194cae16d213dfc9194180fa3fChung-yih Wang/* current support the following routing entries */
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* route add default dev wlan0 */
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* route add default gw 192.168.20.1 dev wlan0 */
4898c297f2448fd8194cae16d213dfc9194180fa3fChung-yih Wang/* route add net 192.168.1.1 netmask 255.255.255.0 gw 172.24.192.10 */
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint route_main(int argc, char *argv[])
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct ifreq ifr;
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int s,i;
5483ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat    struct rtentry rt;
5583ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat    struct sockaddr_in ina;
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
5783ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat    if (!argc)
5883ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat        return 0;
5983ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    strncpy(ifr.ifr_name, argv[0], IFNAMSIZ);
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ifr.ifr_name[IFNAMSIZ-1] = 0;
6283ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat    ADVANCE(argc, argv);
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
6483ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        die("cannot open control socket\n");
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(argc > 0){
6983ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat        if (!strcmp(argv[0], "add")) {
7083ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat            EXPECT_NEXT(argc, argv);
7183ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat            if (!strcmp(argv[0], "default")) {
7283ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                EXPECT_NEXT(argc, argv);
7383ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                memset((char *) &rt, 0, sizeof(struct rtentry));
7483ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                rt.rt_dst.sa_family = AF_INET;
7583ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                if(!strcmp(argv[0], "dev")) {
7683ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                    EXPECT_NEXT(argc, argv);
7783ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                    rt.rt_flags = RTF_UP | RTF_HOST;
7883ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                    rt.rt_dev = argv[0];
7983ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                    if (ioctl(s, SIOCADDRT, &rt) < 0)
8083ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                        die("SIOCADDRT\n");
8183ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                } else if (!strcmp(argv[0], "gw")) {
8283ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                    EXPECT_NEXT(argc, argv);
8383ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                    rt.rt_flags = RTF_UP | RTF_GATEWAY;
8483ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                    init_sockaddr_in((struct sockaddr_in *)&(rt.rt_genmask), "0.0.0.0");
8583ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                    if(isdigit(argv[0][0])) {
8683ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                        init_sockaddr_in((struct sockaddr_in *)&(rt.rt_gateway), argv[0]);
8783ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                    } else {
8883ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                        die("expecting an IP address for parameter \"gw\"\n");
8983ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                    }
9083ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                    EXPECT_NEXT(argc, argv);
9183ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                    if (!strcmp(argv[0], "dev")) {
9283ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                        EXPECT_NEXT(argc, argv);
9383ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                        rt.rt_dev = argv[0];
9483ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                        if (ioctl(s, SIOCADDRT, &rt) < 0) {
9598c297f2448fd8194cae16d213dfc9194180fa3fChung-yih Wang                            die("SIOCADDRT\n");
9698c297f2448fd8194cae16d213dfc9194180fa3fChung-yih Wang                        }
9783ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                    }
9883ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                }
9983ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat            } else {
10083ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                char keywords[3][10] = { "-net", "netmask", "gw" };
10183ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                struct sockaddr_in *paddr[3] = { &rt.rt_dst, &rt.rt_genmask, &rt.rt_gateway };
10283ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                int k = 0;
10383ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat
10483ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                memset((char *) &rt, 0, sizeof(struct rtentry));
10583ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                rt.rt_flags = RTF_UP | RTF_GATEWAY;
10683ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                do {
10783ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                     if (!strcmp(argv[0], keywords[k])) {
10883ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                         EXPECT_NEXT(argc, argv);
10983ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                         if (isdigit(argv[0][0])) {
11083ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                             init_sockaddr_in(paddr[k], argv[0]);
11183ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                         } else {
11283ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                            die("expecting an IP/MASK address for parameter %s\n", keywords[k]);
11383ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                         }
11483ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                     if (k < 2)
11583ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                         EXPECT_NEXT(argc, argv);
11683ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                     } else {
11783ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                         die("expecting keyword(s)\n");
11883ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                     }
11983ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                 } while (++k < 3);
12083ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat
12183ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                if (ioctl(s, SIOCADDRT, &rt) < 0) {
12283ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                    die("SIOCADDRT\n");
12383ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat                }
12483ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat            }
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
12683ec181dc74d5dab4110e1895e62f1bdbf6d7d7aSan Mehat        ADVANCE(argc, argv);
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
131