summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChia-chi Yeh2009-06-29 14:54:08 -0500
committerChia-chi Yeh2009-06-29 15:56:35 -0500
commit4a1465fefff747bebcf95b61ad4598e2c5417de5 (patch)
treec8d3897e46599f76dc02b09f6d500a273844d73b
parent9f9c951ad3329a4d8bc84b48a2b125a67ba9979f (diff)
downloadplatform-system-core-4a1465fefff747bebcf95b61ad4598e2c5417de5.tar.gz
platform-system-core-4a1465fefff747bebcf95b61ad4598e2c5417de5.tar.xz
platform-system-core-4a1465fefff747bebcf95b61ad4598e2c5417de5.zip
toolbox: Revise route utility.
Add copyright header. Returns errno when something goes wrong. Otherwise returns 0. When the route entry exists, treat it as a success.
-rw-r--r--toolbox/route.c185
1 files changed, 79 insertions, 106 deletions
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 @@
1/*
2 * Copyright (c) 2009, The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google, Inc. nor the names of its contributors
15 * may be used to endorse or promote products derived from this
16 * software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
1 31
2#include <stdio.h> 32#include <stdio.h>
3#include <stdlib.h>
4#include <unistd.h>
5#include <stdarg.h>
6
7#include <errno.h>
8#include <string.h> 33#include <string.h>
9#include <ctype.h> 34#include <errno.h>
10 35#include <sys/ioctl.h>
36#include <sys/types.h>
11#include <sys/socket.h> 37#include <sys/socket.h>
12#include <netinet/in.h> 38#include <netinet/in.h>
13#include <linux/if.h>
14#include <linux/sockios.h>
15#include <arpa/inet.h> 39#include <arpa/inet.h>
16#include <linux/route.h> 40#include <linux/route.h>
17 41
18static void die(const char *fmt, ...) 42static inline int set_address(const char *address, struct sockaddr *sa) {
19{ 43 return inet_aton(address, &((struct sockaddr_in *)sa)->sin_addr);
20 va_list p;
21
22 va_start(p, fmt);
23 fprintf(stderr,"error(%s): ", strerror(errno));
24 fprintf(stderr, fmt, p);
25 va_end(p);
26 exit(-1);
27} 44}
28 45
29static inline void init_sockaddr_in(struct sockaddr_in *sin, const char *addr)
30{
31 sin->sin_family = AF_INET;
32 sin->sin_port = 0;
33 sin->sin_addr.s_addr = inet_addr(addr);
34}
35
36#define ADVANCE(argc, argv) do { argc--, argv++; } while(0)
37#define EXPECT_NEXT(argc, argv) do { \
38 ADVANCE(argc, argv); \
39 if (0 == argc) { \
40 errno = EINVAL; \
41 die("expecting one more argument"); \
42 } \
43} while(0)
44
45/* current support the following routing entries */ 46/* current support the following routing entries */
46/* route add default dev wlan0 */ 47/* route add default dev wlan0 */
47/* route add default gw 192.168.20.1 dev wlan0 */ 48/* route add default gw 192.168.1.1 dev wlan0 */
48/* route add net 192.168.1.1 netmask 255.255.255.0 gw 172.24.192.10 */ 49/* route add -net 192.168.1.2 netmask 255.255.255.0 gw 192.168.1.1 */
49 50
50int route_main(int argc, char *argv[]) 51int route_main(int argc, char *argv[])
51{ 52{
52 struct ifreq ifr; 53 struct rtentry rt = {
53 int s,i; 54 .rt_dst = {.sa_family = AF_INET},
54 struct rtentry rt; 55 .rt_genmask = {.sa_family = AF_INET},
55 struct sockaddr_in ina; 56 .rt_gateway = {.sa_family = AF_INET},
56 57 };
57 if (!argc)
58 return 0;
59
60 strncpy(ifr.ifr_name, argv[0], IFNAMSIZ);
61 ifr.ifr_name[IFNAMSIZ-1] = 0;
62 ADVANCE(argc, argv);
63 58
64 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 59 errno = EINVAL;
65 die("cannot open control socket\n"); 60 if (argc > 2 && !strcmp(argv[1], "add")) {
66 } 61 if (!strcmp(argv[2], "default")) {
67 62 /* route add default dev wlan0 */
68 while(argc > 0){ 63 if (argc > 4 && !strcmp(argv[3], "dev")) {
69 if (!strcmp(argv[0], "add")) { 64 rt.rt_flags = RTF_UP | RTF_HOST;
70 EXPECT_NEXT(argc, argv); 65 rt.rt_dev = argv[4];
71 if (!strcmp(argv[0], "default")) { 66 errno = 0;
72 EXPECT_NEXT(argc, argv); 67 goto apply;
73 memset((char *) &rt, 0, sizeof(struct rtentry)); 68 }
74 rt.rt_dst.sa_family = AF_INET;
75 if(!strcmp(argv[0], "dev")) {
76 EXPECT_NEXT(argc, argv);
77 rt.rt_flags = RTF_UP | RTF_HOST;
78 rt.rt_dev = argv[0];
79 if (ioctl(s, SIOCADDRT, &rt) < 0)
80 die("SIOCADDRT\n");
81 } else if (!strcmp(argv[0], "gw")) {
82 EXPECT_NEXT(argc, argv);
83 rt.rt_flags = RTF_UP | RTF_GATEWAY;
84 init_sockaddr_in((struct sockaddr_in *)&(rt.rt_genmask), "0.0.0.0");
85 if(isdigit(argv[0][0])) {
86 init_sockaddr_in((struct sockaddr_in *)&(rt.rt_gateway), argv[0]);
87 } else {
88 die("expecting an IP address for parameter \"gw\"\n");
89 }
90 EXPECT_NEXT(argc, argv);
91 if (!strcmp(argv[0], "dev")) {
92 EXPECT_NEXT(argc, argv);
93 rt.rt_dev = argv[0];
94 if (ioctl(s, SIOCADDRT, &rt) < 0) {
95 die("SIOCADDRT\n");
96 }
97 }
98 }
99 } else {
100 char keywords[3][10] = { "-net", "netmask", "gw" };
101 struct sockaddr_in *paddr[3] = { &rt.rt_dst, &rt.rt_genmask, &rt.rt_gateway };
102 int k = 0;
103 69
104 memset((char *) &rt, 0, sizeof(struct rtentry)); 70 /* route add default gw 192.168.1.1 dev wlan0 */
71 if (argc > 6 && !strcmp(argv[3], "gw") && !strcmp(argv[5], "dev")) {
105 rt.rt_flags = RTF_UP | RTF_GATEWAY; 72 rt.rt_flags = RTF_UP | RTF_GATEWAY;
106 do { 73 rt.rt_dev = argv[6];
107 if (!strcmp(argv[0], keywords[k])) { 74 if (set_address(argv[4], &rt.rt_gateway)) {
108 EXPECT_NEXT(argc, argv); 75 errno = 0;
109 if (isdigit(argv[0][0])) {
110 init_sockaddr_in(paddr[k], argv[0]);
111 } else {
112 die("expecting an IP/MASK address for parameter %s\n", keywords[k]);
113 }
114 if (k < 2)
115 EXPECT_NEXT(argc, argv);
116 } else {
117 die("expecting keyword(s)\n");
118 }
119 } while (++k < 3);
120
121 if (ioctl(s, SIOCADDRT, &rt) < 0) {
122 die("SIOCADDRT\n");
123 } 76 }
77 goto apply;
124 } 78 }
125 } 79 }
126 ADVANCE(argc, argv); 80
81 /* route add -net 192.168.1.2 netmask 255.255.255.0 gw 192.168.1.1 */
82 if (argc > 7 && !strcmp(argv[2], "-net") &&
83 !strcmp(argv[4], "netmask") && !strcmp(argv[6], "gw")) {
84 rt.rt_flags = RTF_UP | RTF_GATEWAY;
85 if (set_address(argv[3], &rt.rt_dst) &&
86 set_address(argv[5], &rt.rt_genmask) &&
87 set_address(argv[7], &rt.rt_gateway)) {
88 errno = 0;
89 }
90 goto apply;
91 }
127 } 92 }
128 93
129 return 0; 94apply:
95 if (!errno) {
96 int s = socket(AF_INET, SOCK_DGRAM, 0);
97 if (s != -1 && (ioctl(s, SIOCADDRT, &rt) != -1 || errno == EEXIST)) {
98 return 0;
99 }
100 }
101 puts(strerror(errno));
102 return errno;
130} 103}