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 32 #include <netinet/in.h> 33 #include <netinet/ip.h> 34 #include <netinet/ip_icmp.h> 35 #include <netinet/udp.h> 36 #include <netinet/tcp.h> 37 #include <netinet/ip6.h> 38 #include <netinet/icmp6.h> 39 #include <linux/icmp.h> 40 41 #include <sys/capability.h> 42 #include <sys/uio.h> 43 #include <linux/prctl.h> 44 #include <linux/if.h> 45 #include <linux/if_tun.h> 46 #include <linux/if_ether.h> 47 48 #include <private/android_filesystem_config.h> 49 50 #include "ipv4.h" 51 #include "ipv6.h" 52 #include "translate.h" 53 #include "clatd.h" 54 #include "config.h" 55 #include "logging.h" 56 #include "setif.h" 57 #include "setroute.h" 58 #include "mtu.h" 59 #include "getaddr.h" 60 #include "dump.h" 61 62 #define DEVICENAME6 "clat" 63 #define DEVICENAME4 "clat4" 64 65 int forwarding_fd = -1; 66 volatile sig_atomic_t running = 1; 67 68 struct tun_data { 69 char device6[IFNAMSIZ], device4[IFNAMSIZ]; 70 int fd6, fd4; 71 }; 72 73 /* function: set_forwarding 74 * enables/disables ipv6 forwarding 75 */ 76 void set_forwarding(int fd, const char *setting) { 77 /* we have to forward packets from the WAN to the tun interface */ 78 if(write(fd, setting, strlen(setting)) < 0) { 79 logmsg(ANDROID_LOG_FATAL,"set_forwarding(%s) failed: %s", setting, strerror(errno)); 80 exit(1); 81 } 82 } 83 84 /* function: stop_loop 85 * signal handler: stop the event loop 86 */ 87 void stop_loop(int signal) { 88 running = 0; 89 } 90 91 /* function: tun_open 92 * tries to open the tunnel device 93 */ 94 int tun_open() { 95 int fd; 96 97 fd = open("/dev/tun", O_RDWR); 98 if(fd < 0) { 99 fd = open("/dev/net/tun", O_RDWR); 100 } 101 102 return fd; 103 } 104 105 /* function: tun_alloc 106 * creates a tun interface and names it 107 * dev - the name for the new tun device 108 */ 109 int tun_alloc(char *dev, int fd) { 110 struct ifreq ifr; 111 int err; 112 113 memset(&ifr, 0, sizeof(ifr)); 114 115 ifr.ifr_flags = IFF_TUN; 116 if( *dev ) { 117 strncpy(ifr.ifr_name, dev, IFNAMSIZ); 118 ifr.ifr_name[IFNAMSIZ-1] = '\0'; 119 } 120 121 if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){ 122 close(fd); 123 return err; 124 } 125 strcpy(dev, ifr.ifr_name); 126 return 0; 127 } 128 129 /* function: deconfigure_tun_ipv6 130 * removes the ipv6 route 131 * tunnel - tun device data 132 */ 133 void deconfigure_tun_ipv6(const struct tun_data *tunnel) { 134 int status; 135 136 status = if_route(tunnel->device6, AF_INET6, &Global_Clatd_Config.ipv6_local_subnet, 137 128, NULL, 1, 0, ROUTE_DELETE); 138 if(status < 0) { 139 logmsg(ANDROID_LOG_WARN,"deconfigure_tun_ipv6/if_route(6) failed: %s",strerror(-status)); 140 } 141 } 142 143 /* function: configure_tun_ipv6 144 * configures the ipv6 route 145 * note: routes a /128 out of the (assumed routed to us) /64 to the CLAT interface 146 * tunnel - tun device data 147 */ 148 void configure_tun_ipv6(const struct tun_data *tunnel) { 149 struct in6_addr local_nat64_prefix_6; 150 int status; 151 152 status = if_route(tunnel->device6, AF_INET6, &Global_Clatd_Config.ipv6_local_subnet, 153 128, NULL, 1, 0, ROUTE_CREATE); 154 if(status < 0) { 155 logmsg(ANDROID_LOG_FATAL,"configure_tun_ipv6/if_route(6) failed: %s",strerror(-status)); 156 exit(1); 157 } 158 } 159 160 /* function: interface_poll 161 * polls the uplink network interface for address changes 162 * tunnel - tun device data 163 */ 164 void interface_poll(const struct tun_data *tunnel) { 165 union anyip *interface_ip; 166 167 interface_ip = getinterface_ip(Global_Clatd_Config.default_pdp_interface, AF_INET6); 168 if(!interface_ip) { 169 logmsg(ANDROID_LOG_WARN,"unable to find an ipv6 ip on interface %s",Global_Clatd_Config.default_pdp_interface); 170 return; 171 } 172 173 config_generate_local_ipv6_subnet(&interface_ip->ip6); 174 175 if(!IN6_ARE_ADDR_EQUAL(&interface_ip->ip6, &Global_Clatd_Config.ipv6_local_subnet)) { 176 char from_addr[INET6_ADDRSTRLEN], to_addr[INET6_ADDRSTRLEN]; 177 inet_ntop(AF_INET6, &Global_Clatd_Config.ipv6_local_subnet, from_addr, sizeof(from_addr)); 178 inet_ntop(AF_INET6, &interface_ip->ip6, to_addr, sizeof(to_addr)); 179 logmsg(ANDROID_LOG_WARN, "clat subnet changed from %s to %s", from_addr, to_addr); 180 181 // remove old route 182 deconfigure_tun_ipv6(tunnel); 183 184 // add new route, start translating packets to the new prefix 185 memcpy(&Global_Clatd_Config.ipv6_local_subnet, &interface_ip->ip6, sizeof(struct in6_addr)); 186 configure_tun_ipv6(tunnel); 187 } 188 189 free(interface_ip); 190 } 191 192 /* function: configure_tun_ip 193 * configures the ipv4 and ipv6 addresses on the tunnel interface 194 * tunnel - tun device data 195 */ 196 void configure_tun_ip(const struct tun_data *tunnel) { 197 int status; 198 199 // Configure the interface before bringing it up. As soon as we bring the interface up, the 200 // framework will be notified and will assume the interface's configuration has been finalized. 201 status = add_address(tunnel->device4, AF_INET, &Global_Clatd_Config.ipv4_local_subnet, 202 32, &Global_Clatd_Config.ipv4_local_subnet); 203 if(status < 0) { 204 logmsg(ANDROID_LOG_FATAL,"configure_tun_ip/if_address(4) failed: %s",strerror(-status)); 205 exit(1); 206 } 207 208 if((status = if_up(tunnel->device6, Global_Clatd_Config.mtu)) < 0) { 209 logmsg(ANDROID_LOG_FATAL,"configure_tun_ip/if_up(6) failed: %s",strerror(-status)); 210 exit(1); 211 } 212 213 if((status = if_up(tunnel->device4, Global_Clatd_Config.ipv4mtu)) < 0) { 214 logmsg(ANDROID_LOG_FATAL,"configure_tun_ip/if_up(4) failed: %s",strerror(-status)); 215 exit(1); 216 } 217 218 configure_tun_ipv6(tunnel); 219 } 220 221 /* function: drop_root 222 * drops root privs but keeps the needed capability 223 */ 224 void drop_root() { 225 gid_t groups[] = { AID_INET }; 226 if(setgroups(sizeof(groups)/sizeof(groups[0]), groups) < 0) { 227 logmsg(ANDROID_LOG_FATAL,"drop_root/setgroups failed: %s",strerror(errno)); 228 exit(1); 229 } 230 231 prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); 232 233 if(setgid(AID_CLAT) < 0) { 234 logmsg(ANDROID_LOG_FATAL,"drop_root/setgid failed: %s",strerror(errno)); 235 exit(1); 236 } 237 if(setuid(AID_CLAT) < 0) { 238 logmsg(ANDROID_LOG_FATAL,"drop_root/setuid failed: %s",strerror(errno)); 239 exit(1); 240 } 241 242 struct __user_cap_header_struct header; 243 struct __user_cap_data_struct cap; 244 memset(&header, 0, sizeof(header)); 245 memset(&cap, 0, sizeof(cap)); 246 247 header.version = _LINUX_CAPABILITY_VERSION; 248 header.pid = 0; // 0 = change myself 249 cap.effective = cap.permitted = (1 << CAP_NET_ADMIN); 250 251 if(capset(&header, &cap) < 0) { 252 logmsg(ANDROID_LOG_FATAL,"drop_root/capset failed: %s",strerror(errno)); 253 exit(1); 254 } 255 } 256 257 /* function: configure_interface 258 * reads the configuration and applies it to the interface 259 * uplink_interface - network interface to use to reach the ipv6 internet 260 * plat_prefix - PLAT prefix to use 261 * tunnel - tun device data 262 */ 263 void configure_interface(const char *uplink_interface, const char *plat_prefix, struct tun_data *tunnel) { 264 int error; 265 266 if(!read_config("/system/etc/clatd.conf", uplink_interface, plat_prefix)) { 267 logmsg(ANDROID_LOG_FATAL,"read_config failed"); 268 exit(1); 269 } 270 271 if(Global_Clatd_Config.mtu > MAXMTU) { 272 logmsg(ANDROID_LOG_WARN,"Max MTU is %d, requested %d", MAXMTU, Global_Clatd_Config.mtu); 273 Global_Clatd_Config.mtu = MAXMTU; 274 } 275 if(Global_Clatd_Config.mtu <= 0) { 276 Global_Clatd_Config.mtu = getifmtu(Global_Clatd_Config.default_pdp_interface); 277 logmsg(ANDROID_LOG_WARN,"ifmtu=%d",Global_Clatd_Config.mtu); 278 } 279 if(Global_Clatd_Config.mtu < 1280) { 280 logmsg(ANDROID_LOG_WARN,"mtu too small = %d", Global_Clatd_Config.mtu); 281 Global_Clatd_Config.mtu = 1280; 282 } 283 284 if(Global_Clatd_Config.ipv4mtu <= 0 || (Global_Clatd_Config.ipv4mtu > Global_Clatd_Config.mtu - 20)) { 285 Global_Clatd_Config.ipv4mtu = Global_Clatd_Config.mtu-20; 286 logmsg(ANDROID_LOG_WARN,"ipv4mtu now set to = %d",Global_Clatd_Config.ipv4mtu); 287 } 288 289 error = tun_alloc(tunnel->device6, tunnel->fd6); 290 if(error < 0) { 291 logmsg(ANDROID_LOG_FATAL,"tun_alloc failed: %s",strerror(errno)); 292 exit(1); 293 } 294 295 error = tun_alloc(tunnel->device4, tunnel->fd4); 296 if(error < 0) { 297 logmsg(ANDROID_LOG_FATAL,"tun_alloc/4 failed: %s",strerror(errno)); 298 exit(1); 299 } 300 301 configure_tun_ip(tunnel); 302 } 303 304 /* function: packet_handler 305 * takes a tun header and a packet and sends it down the stack 306 * tunnel - tun device data 307 * tun_header - tun header 308 * packet - packet 309 * packetsize - size of packet 310 */ 311 void packet_handler(const struct tun_data *tunnel, struct tun_pi *tun_header, const char *packet, 312 size_t packetsize) { 313 int fd; 314 int iov_len = 0; 315 316 // Allocate buffers for all packet headers. 317 struct tun_pi tun_targ; 318 char iphdr[sizeof(struct ip6_hdr)]; 319 char transporthdr[MAX_TCP_HDR]; 320 char icmp_iphdr[sizeof(struct ip6_hdr)]; 321 char icmp_transporthdr[MAX_TCP_HDR]; 322 323 // iovec of the packets we'll send. This gets passed down to the translation functions. 324 clat_packet out = { 325 { &tun_targ, sizeof(tun_targ) }, // Tunnel header. 326 { iphdr, 0 }, // IP header. 327 { transporthdr, 0 }, // Transport layer header. 328 { icmp_iphdr, 0 }, // ICMP error inner IP header. 329 { icmp_transporthdr, 0 }, // ICMP error transport layer header. 330 { NULL, 0 }, // Payload. No buffer, it's a pointer to the original payload. 331 }; 332 333 if(tun_header->flags != 0) { 334 logmsg(ANDROID_LOG_WARN,"packet_handler: unexpected flags = %d", tun_header->flags); 335 } 336 337 if(ntohs(tun_header->proto) == ETH_P_IP) { 338 fd = tunnel->fd6; 339 fill_tun_header(&tun_targ, ETH_P_IPV6); 340 iov_len = ipv4_packet(out, CLAT_POS_IPHDR, packet, packetsize); 341 } else if(ntohs(tun_header->proto) == ETH_P_IPV6) { 342 fd = tunnel->fd4; 343 fill_tun_header(&tun_targ, ETH_P_IP); 344 iov_len = ipv6_packet(out, CLAT_POS_IPHDR, packet, packetsize); 345 } else { 346 logmsg(ANDROID_LOG_WARN,"packet_handler: unknown packet type = %x",tun_header->proto); 347 } 348 349 if (iov_len > 0) { 350 writev(fd, out, iov_len); 351 } 352 } 353 354 /* function: read_packet 355 * reads a packet from the tunnel fd and passes it down the stack 356 * active_fd - tun file descriptor marked ready for reading 357 * tunnel - tun device data 358 */ 359 void read_packet(int active_fd, const struct tun_data *tunnel) { 360 ssize_t readlen; 361 char packet[PACKETLEN]; 362 363 // in case something ignores the packet length 364 memset(packet, 0, PACKETLEN); 365 366 readlen = read(active_fd,packet,PACKETLEN); 367 368 if(readlen < 0) { 369 logmsg(ANDROID_LOG_WARN,"read_packet/read error: %s", strerror(errno)); 370 return; 371 } else if(readlen == 0) { 372 logmsg(ANDROID_LOG_WARN,"read_packet/tun interface removed"); 373 running = 0; 374 } else { 375 struct tun_pi tun_header; 376 ssize_t header_size = sizeof(struct tun_pi); 377 378 if(readlen < header_size) { 379 logmsg(ANDROID_LOG_WARN,"read_packet/short read: got %ld bytes", readlen); 380 return; 381 } 382 383 packet_handler(tunnel, (struct tun_pi *) packet, packet + header_size, readlen - header_size); 384 } 385 } 386 387 /* function: event_loop 388 * reads packets from the tun network interface and passes them down the stack 389 * tunnel - tun device data 390 */ 391 void event_loop(const struct tun_data *tunnel) { 392 time_t last_interface_poll; 393 struct pollfd wait_fd[2]; 394 395 // start the poll timer 396 last_interface_poll = time(NULL); 397 398 wait_fd[0].fd = tunnel->fd6; 399 wait_fd[0].events = POLLIN; 400 wait_fd[0].revents = 0; 401 wait_fd[1].fd = tunnel->fd4; 402 wait_fd[1].events = POLLIN; 403 wait_fd[1].revents = 0; 404 405 while(running) { 406 if(poll(wait_fd, 2, NO_TRAFFIC_INTERFACE_POLL_FREQUENCY*1000) == -1) { 407 if(errno != EINTR) { 408 logmsg(ANDROID_LOG_WARN,"event_loop/poll returned an error: %s",strerror(errno)); 409 } 410 } else { 411 int i; 412 for(i = 0; i < 2; i++) { 413 if((wait_fd[i].revents & POLLIN) != 0) { 414 read_packet(wait_fd[i].fd,tunnel); 415 } 416 } 417 } 418 419 time_t now = time(NULL); 420 if(last_interface_poll < (now - INTERFACE_POLL_FREQUENCY)) { 421 interface_poll(tunnel); 422 last_interface_poll = now; 423 } 424 } 425 } 426 427 /* function: print_help 428 * in case the user is running this on the command line 429 */ 430 void print_help() { 431 printf("android-clat arguments:\n"); 432 printf("-i [uplink interface]\n"); 433 printf("-p [plat prefix]\n"); 434 } 435 436 /* function: main 437 * allocate and setup the tun device, then run the event loop 438 */ 439 int main(int argc, char **argv) { 440 struct tun_data tunnel; 441 int opt; 442 char *uplink_interface = NULL, *plat_prefix = NULL; 443 444 strcpy(tunnel.device6, DEVICENAME6); 445 strcpy(tunnel.device4, DEVICENAME4); 446 447 while((opt = getopt(argc, argv, "i:p:h")) != -1) { 448 switch(opt) { 449 case 'i': 450 uplink_interface = optarg; 451 break; 452 case 'p': 453 plat_prefix = optarg; 454 break; 455 case 'h': 456 default: 457 print_help(); 458 exit(1); 459 break; 460 } 461 } 462 463 if(uplink_interface == NULL) { 464 logmsg(ANDROID_LOG_FATAL, "clatd called without an interface"); 465 printf("I need an interface\n"); 466 exit(1); 467 } 468 logmsg(ANDROID_LOG_INFO, "Starting clat version %s on %s", CLATD_VERSION, uplink_interface); 469 470 // open the tunnel device before dropping privs 471 tunnel.fd6 = tun_open(); 472 if(tunnel.fd6 < 0) { 473 logmsg(ANDROID_LOG_FATAL, "tun_open failed: %s", strerror(errno)); 474 exit(1); 475 } 476 477 tunnel.fd4 = tun_open(); 478 if(tunnel.fd4 < 0) { 479 logmsg(ANDROID_LOG_FATAL, "tun_open4 failed: %s", strerror(errno)); 480 exit(1); 481 } 482 483 // open the forwarding configuration before dropping privs 484 forwarding_fd = open("/proc/sys/net/ipv6/conf/all/forwarding", O_RDWR); 485 if(forwarding_fd < 0) { 486 logmsg(ANDROID_LOG_FATAL,"open /proc/sys/net/ipv6/conf/all/forwarding failed: %s", 487 strerror(errno)); 488 exit(1); 489 } 490 491 // run under a regular user 492 drop_root(); 493 494 // When run from netd, the environment variable ANDROID_DNS_MODE is set to 495 // "local", but that only works for the netd process itself. 496 unsetenv("ANDROID_DNS_MODE"); 497 498 configure_interface(uplink_interface, plat_prefix, &tunnel); 499 500 set_forwarding(forwarding_fd,"1\n"); 501 502 // Loop until someone sends us a signal or brings down the tun interface. 503 if(signal(SIGTERM, stop_loop) == SIG_ERR) { 504 logmsg(ANDROID_LOG_FATAL, "sigterm handler failed: %s", strerror(errno)); 505 exit(1); 506 } 507 event_loop(&tunnel); 508 509 set_forwarding(forwarding_fd,"0\n"); 510 logmsg(ANDROID_LOG_INFO,"Shutting down clat on %s", uplink_interface); 511 512 return 0; 513 } 514