| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright 2012 Daniel Drown | 
|  | 3 | * | 
|  | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 5 | * you may not use this file except in compliance with the License. | 
|  | 6 | * You may obtain a copy of the License at | 
|  | 7 | * | 
|  | 8 | * http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 9 | * | 
|  | 10 | * Unless required by applicable law or agreed to in writing, software | 
|  | 11 | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 13 | * See the License for the specific language governing permissions and | 
|  | 14 | * limitations under the License. | 
|  | 15 | * | 
|  | 16 | * clatd.c - tun interface setup and main event loop | 
|  | 17 | */ | 
|  | 18 | #include <poll.h> | 
|  | 19 | #include <signal.h> | 
|  | 20 | #include <time.h> | 
|  | 21 | #include <stdio.h> | 
|  | 22 | #include <sys/types.h> | 
|  | 23 | #include <sys/ioctl.h> | 
|  | 24 | #include <sys/stat.h> | 
|  | 25 | #include <string.h> | 
|  | 26 | #include <errno.h> | 
|  | 27 | #include <stdlib.h> | 
|  | 28 | #include <unistd.h> | 
|  | 29 | #include <arpa/inet.h> | 
|  | 30 | #include <fcntl.h> | 
|  | 31 |  | 
| Nick Kralevich | 2edb756 | 2013-02-28 14:15:22 -0800 | [diff] [blame] | 32 | #include <sys/capability.h> | 
| Lorenzo Colitti | d908418 | 2013-03-22 00:42:21 +0900 | [diff] [blame] | 33 | #include <sys/uio.h> | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 34 | #include <linux/prctl.h> | 
|  | 35 | #include <linux/if.h> | 
|  | 36 | #include <linux/if_tun.h> | 
|  | 37 | #include <linux/if_ether.h> | 
|  | 38 |  | 
|  | 39 | #include <private/android_filesystem_config.h> | 
|  | 40 |  | 
| Lorenzo Colitti | d908418 | 2013-03-22 00:42:21 +0900 | [diff] [blame] | 41 | #include "translate.h" | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 42 | #include "clatd.h" | 
|  | 43 | #include "config.h" | 
|  | 44 | #include "logging.h" | 
|  | 45 | #include "setif.h" | 
|  | 46 | #include "setroute.h" | 
|  | 47 | #include "mtu.h" | 
|  | 48 | #include "getaddr.h" | 
|  | 49 | #include "dump.h" | 
|  | 50 |  | 
|  | 51 | #define DEVICENAME6 "clat" | 
|  | 52 | #define DEVICENAME4 "clat4" | 
|  | 53 |  | 
|  | 54 | int forwarding_fd = -1; | 
|  | 55 | volatile sig_atomic_t running = 1; | 
|  | 56 |  | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 57 | /* function: set_forwarding | 
|  | 58 | * enables/disables ipv6 forwarding | 
|  | 59 | */ | 
|  | 60 | void set_forwarding(int fd, const char *setting) { | 
|  | 61 | /* we have to forward packets from the WAN to the tun interface */ | 
|  | 62 | if(write(fd, setting, strlen(setting)) < 0) { | 
|  | 63 | logmsg(ANDROID_LOG_FATAL,"set_forwarding(%s) failed: %s", setting, strerror(errno)); | 
|  | 64 | exit(1); | 
|  | 65 | } | 
|  | 66 | } | 
|  | 67 |  | 
| Lorenzo Colitti | baf6299 | 2013-03-01 20:29:39 +0900 | [diff] [blame] | 68 | /* function: stop_loop | 
|  | 69 | * signal handler: stop the event loop | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 70 | */ | 
| Lorenzo Colitti | 9477a46 | 2013-11-18 15:56:02 +0900 | [diff] [blame] | 71 | void stop_loop() { | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 72 | running = 0; | 
|  | 73 | } | 
|  | 74 |  | 
|  | 75 | /* function: tun_open | 
|  | 76 | * tries to open the tunnel device | 
|  | 77 | */ | 
|  | 78 | int tun_open() { | 
|  | 79 | int fd; | 
|  | 80 |  | 
|  | 81 | fd = open("/dev/tun", O_RDWR); | 
|  | 82 | if(fd < 0) { | 
|  | 83 | fd = open("/dev/net/tun", O_RDWR); | 
|  | 84 | } | 
|  | 85 |  | 
|  | 86 | return fd; | 
|  | 87 | } | 
|  | 88 |  | 
|  | 89 | /* function: tun_alloc | 
|  | 90 | * creates a tun interface and names it | 
|  | 91 | * dev - the name for the new tun device | 
|  | 92 | */ | 
|  | 93 | int tun_alloc(char *dev, int fd) { | 
|  | 94 | struct ifreq ifr; | 
|  | 95 | int err; | 
|  | 96 |  | 
|  | 97 | memset(&ifr, 0, sizeof(ifr)); | 
|  | 98 |  | 
|  | 99 | ifr.ifr_flags = IFF_TUN; | 
|  | 100 | if( *dev ) { | 
|  | 101 | strncpy(ifr.ifr_name, dev, IFNAMSIZ); | 
|  | 102 | ifr.ifr_name[IFNAMSIZ-1] = '\0'; | 
|  | 103 | } | 
|  | 104 |  | 
|  | 105 | if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){ | 
|  | 106 | close(fd); | 
|  | 107 | return err; | 
|  | 108 | } | 
|  | 109 | strcpy(dev, ifr.ifr_name); | 
|  | 110 | return 0; | 
|  | 111 | } | 
|  | 112 |  | 
|  | 113 | /* function: deconfigure_tun_ipv6 | 
|  | 114 | * removes the ipv6 route | 
|  | 115 | * tunnel - tun device data | 
|  | 116 | */ | 
|  | 117 | void deconfigure_tun_ipv6(const struct tun_data *tunnel) { | 
|  | 118 | int status; | 
|  | 119 |  | 
|  | 120 | status = if_route(tunnel->device6, AF_INET6, &Global_Clatd_Config.ipv6_local_subnet, | 
|  | 121 | 128, NULL, 1, 0, ROUTE_DELETE); | 
|  | 122 | if(status < 0) { | 
|  | 123 | logmsg(ANDROID_LOG_WARN,"deconfigure_tun_ipv6/if_route(6) failed: %s",strerror(-status)); | 
|  | 124 | } | 
|  | 125 | } | 
|  | 126 |  | 
|  | 127 | /* function: configure_tun_ipv6 | 
|  | 128 | * configures the ipv6 route | 
|  | 129 | * note: routes a /128 out of the (assumed routed to us) /64 to the CLAT interface | 
|  | 130 | * tunnel - tun device data | 
|  | 131 | */ | 
|  | 132 | void configure_tun_ipv6(const struct tun_data *tunnel) { | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 133 | int status; | 
|  | 134 |  | 
|  | 135 | status = if_route(tunnel->device6, AF_INET6, &Global_Clatd_Config.ipv6_local_subnet, | 
|  | 136 | 128, NULL, 1, 0, ROUTE_CREATE); | 
|  | 137 | if(status < 0) { | 
|  | 138 | logmsg(ANDROID_LOG_FATAL,"configure_tun_ipv6/if_route(6) failed: %s",strerror(-status)); | 
|  | 139 | exit(1); | 
|  | 140 | } | 
|  | 141 | } | 
|  | 142 |  | 
|  | 143 | /* function: interface_poll | 
|  | 144 | * polls the uplink network interface for address changes | 
|  | 145 | * tunnel - tun device data | 
|  | 146 | */ | 
|  | 147 | void interface_poll(const struct tun_data *tunnel) { | 
|  | 148 | union anyip *interface_ip; | 
|  | 149 |  | 
|  | 150 | interface_ip = getinterface_ip(Global_Clatd_Config.default_pdp_interface, AF_INET6); | 
|  | 151 | if(!interface_ip) { | 
|  | 152 | logmsg(ANDROID_LOG_WARN,"unable to find an ipv6 ip on interface %s",Global_Clatd_Config.default_pdp_interface); | 
|  | 153 | return; | 
|  | 154 | } | 
|  | 155 |  | 
|  | 156 | config_generate_local_ipv6_subnet(&interface_ip->ip6); | 
|  | 157 |  | 
|  | 158 | if(!IN6_ARE_ADDR_EQUAL(&interface_ip->ip6, &Global_Clatd_Config.ipv6_local_subnet)) { | 
|  | 159 | char from_addr[INET6_ADDRSTRLEN], to_addr[INET6_ADDRSTRLEN]; | 
|  | 160 | inet_ntop(AF_INET6, &Global_Clatd_Config.ipv6_local_subnet, from_addr, sizeof(from_addr)); | 
|  | 161 | inet_ntop(AF_INET6, &interface_ip->ip6, to_addr, sizeof(to_addr)); | 
|  | 162 | logmsg(ANDROID_LOG_WARN, "clat subnet changed from %s to %s", from_addr, to_addr); | 
|  | 163 |  | 
|  | 164 | // remove old route | 
|  | 165 | deconfigure_tun_ipv6(tunnel); | 
|  | 166 |  | 
|  | 167 | // add new route, start translating packets to the new prefix | 
|  | 168 | memcpy(&Global_Clatd_Config.ipv6_local_subnet, &interface_ip->ip6, sizeof(struct in6_addr)); | 
|  | 169 | configure_tun_ipv6(tunnel); | 
|  | 170 | } | 
|  | 171 |  | 
|  | 172 | free(interface_ip); | 
|  | 173 | } | 
|  | 174 |  | 
|  | 175 | /* function: configure_tun_ip | 
|  | 176 | * configures the ipv4 and ipv6 addresses on the tunnel interface | 
|  | 177 | * tunnel - tun device data | 
|  | 178 | */ | 
|  | 179 | void configure_tun_ip(const struct tun_data *tunnel) { | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 180 | int status; | 
|  | 181 |  | 
| Lorenzo Colitti | 3ca0302 | 2013-03-27 12:39:10 +0900 | [diff] [blame] | 182 | // Configure the interface before bringing it up. As soon as we bring the interface up, the | 
|  | 183 | // framework will be notified and will assume the interface's configuration has been finalized. | 
|  | 184 | status = add_address(tunnel->device4, AF_INET, &Global_Clatd_Config.ipv4_local_subnet, | 
|  | 185 | 32, &Global_Clatd_Config.ipv4_local_subnet); | 
|  | 186 | if(status < 0) { | 
|  | 187 | logmsg(ANDROID_LOG_FATAL,"configure_tun_ip/if_address(4) failed: %s",strerror(-status)); | 
|  | 188 | exit(1); | 
|  | 189 | } | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 190 |  | 
| JP Abgrall | 4e0dd83 | 2013-12-20 14:51:26 -0800 | [diff] [blame] | 191 | status = add_address(tunnel->device6, AF_INET6, &Global_Clatd_Config.ipv6_local_address, | 
|  | 192 | 64, NULL); | 
|  | 193 | if(status < 0) { | 
|  | 194 | logmsg(ANDROID_LOG_FATAL,"configure_tun_ip/if_address(6) failed: %s",strerror(-status)); | 
|  | 195 | exit(1); | 
|  | 196 | } | 
|  | 197 |  | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 198 | if((status = if_up(tunnel->device6, Global_Clatd_Config.mtu)) < 0) { | 
|  | 199 | logmsg(ANDROID_LOG_FATAL,"configure_tun_ip/if_up(6) failed: %s",strerror(-status)); | 
|  | 200 | exit(1); | 
|  | 201 | } | 
| Lorenzo Colitti | 3ca0302 | 2013-03-27 12:39:10 +0900 | [diff] [blame] | 202 |  | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 203 | if((status = if_up(tunnel->device4, Global_Clatd_Config.ipv4mtu)) < 0) { | 
|  | 204 | logmsg(ANDROID_LOG_FATAL,"configure_tun_ip/if_up(4) failed: %s",strerror(-status)); | 
|  | 205 | exit(1); | 
|  | 206 | } | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 207 |  | 
|  | 208 | configure_tun_ipv6(tunnel); | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 209 | } | 
|  | 210 |  | 
|  | 211 | /* function: drop_root | 
|  | 212 | * drops root privs but keeps the needed capability | 
|  | 213 | */ | 
|  | 214 | void drop_root() { | 
|  | 215 | gid_t groups[] = { AID_INET }; | 
|  | 216 | if(setgroups(sizeof(groups)/sizeof(groups[0]), groups) < 0) { | 
|  | 217 | logmsg(ANDROID_LOG_FATAL,"drop_root/setgroups failed: %s",strerror(errno)); | 
|  | 218 | exit(1); | 
|  | 219 | } | 
|  | 220 |  | 
|  | 221 | prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); | 
|  | 222 |  | 
|  | 223 | if(setgid(AID_CLAT) < 0) { | 
|  | 224 | logmsg(ANDROID_LOG_FATAL,"drop_root/setgid failed: %s",strerror(errno)); | 
|  | 225 | exit(1); | 
|  | 226 | } | 
|  | 227 | if(setuid(AID_CLAT) < 0) { | 
|  | 228 | logmsg(ANDROID_LOG_FATAL,"drop_root/setuid failed: %s",strerror(errno)); | 
|  | 229 | exit(1); | 
|  | 230 | } | 
|  | 231 |  | 
|  | 232 | struct __user_cap_header_struct header; | 
|  | 233 | struct __user_cap_data_struct cap; | 
|  | 234 | memset(&header, 0, sizeof(header)); | 
|  | 235 | memset(&cap, 0, sizeof(cap)); | 
|  | 236 |  | 
|  | 237 | header.version = _LINUX_CAPABILITY_VERSION; | 
|  | 238 | header.pid = 0; // 0 = change myself | 
|  | 239 | cap.effective = cap.permitted = (1 << CAP_NET_ADMIN); | 
|  | 240 |  | 
|  | 241 | if(capset(&header, &cap) < 0) { | 
|  | 242 | logmsg(ANDROID_LOG_FATAL,"drop_root/capset failed: %s",strerror(errno)); | 
|  | 243 | exit(1); | 
|  | 244 | } | 
|  | 245 | } | 
|  | 246 |  | 
|  | 247 | /* function: configure_interface | 
|  | 248 | * reads the configuration and applies it to the interface | 
|  | 249 | * uplink_interface - network interface to use to reach the ipv6 internet | 
|  | 250 | * plat_prefix      - PLAT prefix to use | 
|  | 251 | * tunnel           - tun device data | 
|  | 252 | */ | 
|  | 253 | void configure_interface(const char *uplink_interface, const char *plat_prefix, struct tun_data *tunnel) { | 
|  | 254 | int error; | 
|  | 255 |  | 
|  | 256 | if(!read_config("/system/etc/clatd.conf", uplink_interface, plat_prefix)) { | 
|  | 257 | logmsg(ANDROID_LOG_FATAL,"read_config failed"); | 
|  | 258 | exit(1); | 
|  | 259 | } | 
|  | 260 |  | 
|  | 261 | if(Global_Clatd_Config.mtu > MAXMTU) { | 
|  | 262 | logmsg(ANDROID_LOG_WARN,"Max MTU is %d, requested %d", MAXMTU, Global_Clatd_Config.mtu); | 
|  | 263 | Global_Clatd_Config.mtu = MAXMTU; | 
|  | 264 | } | 
|  | 265 | if(Global_Clatd_Config.mtu <= 0) { | 
|  | 266 | Global_Clatd_Config.mtu = getifmtu(Global_Clatd_Config.default_pdp_interface); | 
|  | 267 | logmsg(ANDROID_LOG_WARN,"ifmtu=%d",Global_Clatd_Config.mtu); | 
|  | 268 | } | 
|  | 269 | if(Global_Clatd_Config.mtu < 1280) { | 
|  | 270 | logmsg(ANDROID_LOG_WARN,"mtu too small = %d", Global_Clatd_Config.mtu); | 
|  | 271 | Global_Clatd_Config.mtu = 1280; | 
|  | 272 | } | 
|  | 273 |  | 
|  | 274 | if(Global_Clatd_Config.ipv4mtu <= 0 || (Global_Clatd_Config.ipv4mtu > Global_Clatd_Config.mtu - 20)) { | 
|  | 275 | Global_Clatd_Config.ipv4mtu = Global_Clatd_Config.mtu-20; | 
|  | 276 | logmsg(ANDROID_LOG_WARN,"ipv4mtu now set to = %d",Global_Clatd_Config.ipv4mtu); | 
|  | 277 | } | 
|  | 278 |  | 
|  | 279 | error = tun_alloc(tunnel->device6, tunnel->fd6); | 
|  | 280 | if(error < 0) { | 
|  | 281 | logmsg(ANDROID_LOG_FATAL,"tun_alloc failed: %s",strerror(errno)); | 
|  | 282 | exit(1); | 
|  | 283 | } | 
|  | 284 |  | 
|  | 285 | error = tun_alloc(tunnel->device4, tunnel->fd4); | 
|  | 286 | if(error < 0) { | 
|  | 287 | logmsg(ANDROID_LOG_FATAL,"tun_alloc/4 failed: %s",strerror(errno)); | 
|  | 288 | exit(1); | 
|  | 289 | } | 
|  | 290 |  | 
|  | 291 | configure_tun_ip(tunnel); | 
|  | 292 | } | 
|  | 293 |  | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 294 | /* function: read_packet | 
|  | 295 | * reads a packet from the tunnel fd and passes it down the stack | 
|  | 296 | * active_fd - tun file descriptor marked ready for reading | 
|  | 297 | * tunnel    - tun device data | 
|  | 298 | */ | 
|  | 299 | void read_packet(int active_fd, const struct tun_data *tunnel) { | 
|  | 300 | ssize_t readlen; | 
|  | 301 | char packet[PACKETLEN]; | 
|  | 302 |  | 
|  | 303 | // in case something ignores the packet length | 
|  | 304 | memset(packet, 0, PACKETLEN); | 
|  | 305 |  | 
|  | 306 | readlen = read(active_fd,packet,PACKETLEN); | 
|  | 307 |  | 
|  | 308 | if(readlen < 0) { | 
|  | 309 | logmsg(ANDROID_LOG_WARN,"read_packet/read error: %s", strerror(errno)); | 
|  | 310 | return; | 
|  | 311 | } else if(readlen == 0) { | 
|  | 312 | logmsg(ANDROID_LOG_WARN,"read_packet/tun interface removed"); | 
|  | 313 | running = 0; | 
|  | 314 | } else { | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 315 | ssize_t header_size = sizeof(struct tun_pi); | 
|  | 316 |  | 
|  | 317 | if(readlen < header_size) { | 
|  | 318 | logmsg(ANDROID_LOG_WARN,"read_packet/short read: got %ld bytes", readlen); | 
|  | 319 | return; | 
|  | 320 | } | 
|  | 321 |  | 
| Lorenzo Colitti | f939060 | 2014-02-13 12:53:35 +0900 | [diff] [blame^] | 322 | translate_packet(tunnel, (struct tun_pi *) packet, packet + header_size, readlen - header_size); | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 323 | } | 
|  | 324 | } | 
|  | 325 |  | 
|  | 326 | /* function: event_loop | 
|  | 327 | * reads packets from the tun network interface and passes them down the stack | 
|  | 328 | * tunnel - tun device data | 
|  | 329 | */ | 
|  | 330 | void event_loop(const struct tun_data *tunnel) { | 
|  | 331 | time_t last_interface_poll; | 
|  | 332 | struct pollfd wait_fd[2]; | 
|  | 333 |  | 
|  | 334 | // start the poll timer | 
|  | 335 | last_interface_poll = time(NULL); | 
|  | 336 |  | 
|  | 337 | wait_fd[0].fd = tunnel->fd6; | 
|  | 338 | wait_fd[0].events = POLLIN; | 
|  | 339 | wait_fd[0].revents = 0; | 
|  | 340 | wait_fd[1].fd = tunnel->fd4; | 
|  | 341 | wait_fd[1].events = POLLIN; | 
|  | 342 | wait_fd[1].revents = 0; | 
|  | 343 |  | 
|  | 344 | while(running) { | 
|  | 345 | if(poll(wait_fd, 2, NO_TRAFFIC_INTERFACE_POLL_FREQUENCY*1000) == -1) { | 
|  | 346 | if(errno != EINTR) { | 
|  | 347 | logmsg(ANDROID_LOG_WARN,"event_loop/poll returned an error: %s",strerror(errno)); | 
|  | 348 | } | 
|  | 349 | } else { | 
|  | 350 | int i; | 
|  | 351 | for(i = 0; i < 2; i++) { | 
|  | 352 | if((wait_fd[i].revents & POLLIN) != 0) { | 
|  | 353 | read_packet(wait_fd[i].fd,tunnel); | 
|  | 354 | } | 
|  | 355 | } | 
|  | 356 | } | 
|  | 357 |  | 
|  | 358 | time_t now = time(NULL); | 
|  | 359 | if(last_interface_poll < (now - INTERFACE_POLL_FREQUENCY)) { | 
|  | 360 | interface_poll(tunnel); | 
|  | 361 | last_interface_poll = now; | 
|  | 362 | } | 
|  | 363 | } | 
|  | 364 | } | 
|  | 365 |  | 
|  | 366 | /* function: print_help | 
|  | 367 | * in case the user is running this on the command line | 
|  | 368 | */ | 
|  | 369 | void print_help() { | 
|  | 370 | printf("android-clat arguments:\n"); | 
|  | 371 | printf("-i [uplink interface]\n"); | 
|  | 372 | printf("-p [plat prefix]\n"); | 
|  | 373 | } | 
|  | 374 |  | 
|  | 375 | /* function: main | 
|  | 376 | * allocate and setup the tun device, then run the event loop | 
|  | 377 | */ | 
|  | 378 | int main(int argc, char **argv) { | 
|  | 379 | struct tun_data tunnel; | 
|  | 380 | int opt; | 
|  | 381 | char *uplink_interface = NULL, *plat_prefix = NULL; | 
|  | 382 |  | 
|  | 383 | strcpy(tunnel.device6, DEVICENAME6); | 
|  | 384 | strcpy(tunnel.device4, DEVICENAME4); | 
|  | 385 |  | 
|  | 386 | while((opt = getopt(argc, argv, "i:p:h")) != -1) { | 
|  | 387 | switch(opt) { | 
|  | 388 | case 'i': | 
|  | 389 | uplink_interface = optarg; | 
|  | 390 | break; | 
|  | 391 | case 'p': | 
|  | 392 | plat_prefix = optarg; | 
|  | 393 | break; | 
|  | 394 | case 'h': | 
|  | 395 | default: | 
|  | 396 | print_help(); | 
|  | 397 | exit(1); | 
|  | 398 | break; | 
|  | 399 | } | 
|  | 400 | } | 
|  | 401 |  | 
|  | 402 | if(uplink_interface == NULL) { | 
| Lorenzo Colitti | d908418 | 2013-03-22 00:42:21 +0900 | [diff] [blame] | 403 | logmsg(ANDROID_LOG_FATAL, "clatd called without an interface"); | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 404 | printf("I need an interface\n"); | 
|  | 405 | exit(1); | 
|  | 406 | } | 
| Lorenzo Colitti | d908418 | 2013-03-22 00:42:21 +0900 | [diff] [blame] | 407 | logmsg(ANDROID_LOG_INFO, "Starting clat version %s on %s", CLATD_VERSION, uplink_interface); | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 408 |  | 
|  | 409 | // open the tunnel device before dropping privs | 
|  | 410 | tunnel.fd6 = tun_open(); | 
|  | 411 | if(tunnel.fd6 < 0) { | 
| JP Abgrall | 4e0dd83 | 2013-12-20 14:51:26 -0800 | [diff] [blame] | 412 | logmsg(ANDROID_LOG_FATAL, "tun_open6 failed: %s", strerror(errno)); | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 413 | exit(1); | 
|  | 414 | } | 
|  | 415 |  | 
|  | 416 | tunnel.fd4 = tun_open(); | 
|  | 417 | if(tunnel.fd4 < 0) { | 
| Lorenzo Colitti | d908418 | 2013-03-22 00:42:21 +0900 | [diff] [blame] | 418 | logmsg(ANDROID_LOG_FATAL, "tun_open4 failed: %s", strerror(errno)); | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 419 | exit(1); | 
|  | 420 | } | 
|  | 421 |  | 
|  | 422 | // open the forwarding configuration before dropping privs | 
|  | 423 | forwarding_fd = open("/proc/sys/net/ipv6/conf/all/forwarding", O_RDWR); | 
|  | 424 | if(forwarding_fd < 0) { | 
| Lorenzo Colitti | d908418 | 2013-03-22 00:42:21 +0900 | [diff] [blame] | 425 | logmsg(ANDROID_LOG_FATAL,"open /proc/sys/net/ipv6/conf/all/forwarding failed: %s", | 
|  | 426 | strerror(errno)); | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 427 | exit(1); | 
|  | 428 | } | 
|  | 429 |  | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 430 | // run under a regular user | 
|  | 431 | drop_root(); | 
|  | 432 |  | 
| Lorenzo Colitti | baf6299 | 2013-03-01 20:29:39 +0900 | [diff] [blame] | 433 | // When run from netd, the environment variable ANDROID_DNS_MODE is set to | 
|  | 434 | // "local", but that only works for the netd process itself. | 
|  | 435 | unsetenv("ANDROID_DNS_MODE"); | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 436 |  | 
|  | 437 | configure_interface(uplink_interface, plat_prefix, &tunnel); | 
|  | 438 |  | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 439 | set_forwarding(forwarding_fd,"1\n"); | 
|  | 440 |  | 
| Lorenzo Colitti | baf6299 | 2013-03-01 20:29:39 +0900 | [diff] [blame] | 441 | // Loop until someone sends us a signal or brings down the tun interface. | 
|  | 442 | if(signal(SIGTERM, stop_loop) == SIG_ERR) { | 
|  | 443 | logmsg(ANDROID_LOG_FATAL, "sigterm handler failed: %s", strerror(errno)); | 
|  | 444 | exit(1); | 
|  | 445 | } | 
|  | 446 | event_loop(&tunnel); | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 447 |  | 
|  | 448 | set_forwarding(forwarding_fd,"0\n"); | 
| Lorenzo Colitti | baf6299 | 2013-03-01 20:29:39 +0900 | [diff] [blame] | 449 | logmsg(ANDROID_LOG_INFO,"Shutting down clat on %s", uplink_interface); | 
| Daniel Drown | a45056e | 2012-03-23 10:42:54 -0500 | [diff] [blame] | 450 |  | 
|  | 451 | return 0; | 
|  | 452 | } |