Re-indent clatd code with clang-format
clang-format --style file -i *.{c,h,cpp}
Bug: 118848635
Test: 1. browse over ipv6-only network
2. atest clatd_test
3. clang-format --style file -i *.{c,h,cpp}
Change-Id: I7389426101df7745370d0ac5c55176cd8fe2b08b
This commit is contained in:
parent
3850bee1d5
commit
c4e591aa04
25 changed files with 907 additions and 906 deletions
68
checksum.c
68
checksum.c
|
|
@ -15,33 +15,33 @@
|
|||
*
|
||||
* checksum.c - ipv4/ipv6 checksum calculation
|
||||
*/
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
|
||||
#include "checksum.h"
|
||||
|
||||
/* function: ip_checksum_add
|
||||
* adds data to a checksum
|
||||
* current - the current checksum (or 0 to start a new checksum)
|
||||
* data - the data to add to the checksum
|
||||
* len - length of data
|
||||
* data - the data to add to the checksum
|
||||
* len - length of data
|
||||
*/
|
||||
uint32_t ip_checksum_add(uint32_t current, const void *data, int len) {
|
||||
uint32_t checksum = current;
|
||||
int left = len;
|
||||
uint32_t checksum = current;
|
||||
int left = len;
|
||||
const uint16_t *data_16 = data;
|
||||
|
||||
while(left > 1) {
|
||||
while (left > 1) {
|
||||
checksum += *data_16;
|
||||
data_16++;
|
||||
left -= 2;
|
||||
}
|
||||
if(left) {
|
||||
if (left) {
|
||||
checksum += *(uint8_t *)data_16;
|
||||
}
|
||||
|
||||
|
|
@ -50,49 +50,48 @@ uint32_t ip_checksum_add(uint32_t current, const void *data, int len) {
|
|||
|
||||
/* function: ip_checksum_fold
|
||||
* folds a 32-bit partial checksum into 16 bits
|
||||
* temp_sum - sum from ip_checksum_add
|
||||
* returns: the folded checksum in network byte order
|
||||
* temp_sum - sum from ip_checksum_add
|
||||
* returns: the folded checksum in network byte order
|
||||
*/
|
||||
uint16_t ip_checksum_fold(uint32_t temp_sum) {
|
||||
while(temp_sum > 0xffff)
|
||||
while (temp_sum > 0xffff) {
|
||||
temp_sum = (temp_sum >> 16) + (temp_sum & 0xFFFF);
|
||||
|
||||
}
|
||||
return temp_sum;
|
||||
}
|
||||
|
||||
/* function: ip_checksum_finish
|
||||
* folds and closes the checksum
|
||||
* temp_sum - sum from ip_checksum_add
|
||||
* returns: a header checksum value in network byte order
|
||||
* temp_sum - sum from ip_checksum_add
|
||||
* returns: a header checksum value in network byte order
|
||||
*/
|
||||
uint16_t ip_checksum_finish(uint32_t temp_sum) {
|
||||
return ~ip_checksum_fold(temp_sum);
|
||||
}
|
||||
uint16_t ip_checksum_finish(uint32_t temp_sum) { return ~ip_checksum_fold(temp_sum); }
|
||||
|
||||
/* function: ip_checksum
|
||||
* combined ip_checksum_add and ip_checksum_finish
|
||||
* data - data to checksum
|
||||
* len - length of data
|
||||
* data - data to checksum
|
||||
* len - length of data
|
||||
*/
|
||||
uint16_t ip_checksum(const void *data, int len) {
|
||||
uint32_t temp_sum;
|
||||
|
||||
temp_sum = ip_checksum_add(0,data,len);
|
||||
temp_sum = ip_checksum_add(0, data, len);
|
||||
return ip_checksum_finish(temp_sum);
|
||||
}
|
||||
|
||||
/* function: ipv6_pseudo_header_checksum
|
||||
* calculate the pseudo header checksum for use in tcp/udp/icmp headers
|
||||
* ip6 - the ipv6 header
|
||||
* len - the transport length (transport header + payload)
|
||||
* protocol - the transport layer protocol, can be different from ip6->ip6_nxt for fragments
|
||||
* ip6 - the ipv6 header
|
||||
* len - the transport length (transport header + payload)
|
||||
* protocol - the transport layer protocol, can be different from ip6->ip6_nxt for fragments
|
||||
*/
|
||||
uint32_t ipv6_pseudo_header_checksum(const struct ip6_hdr *ip6, uint16_t len, uint8_t protocol) {
|
||||
uint32_t checksum_len, checksum_next;
|
||||
checksum_len = htonl((uint32_t) len);
|
||||
checksum_len = htonl((uint32_t)len);
|
||||
checksum_next = htonl(protocol);
|
||||
|
||||
uint32_t current = 0;
|
||||
|
||||
current = ip_checksum_add(current, &(ip6->ip6_src), sizeof(struct in6_addr));
|
||||
current = ip_checksum_add(current, &(ip6->ip6_dst), sizeof(struct in6_addr));
|
||||
current = ip_checksum_add(current, &checksum_len, sizeof(checksum_len));
|
||||
|
|
@ -103,16 +102,17 @@ uint32_t ipv6_pseudo_header_checksum(const struct ip6_hdr *ip6, uint16_t len, ui
|
|||
|
||||
/* function: ipv4_pseudo_header_checksum
|
||||
* calculate the pseudo header checksum for use in tcp/udp headers
|
||||
* ip - the ipv4 header
|
||||
* len - the transport length (transport header + payload)
|
||||
* ip - the ipv4 header
|
||||
* len - the transport length (transport header + payload)
|
||||
*/
|
||||
uint32_t ipv4_pseudo_header_checksum(const struct iphdr *ip, uint16_t len) {
|
||||
uint16_t temp_protocol, temp_length;
|
||||
|
||||
temp_protocol = htons(ip->protocol);
|
||||
temp_length = htons(len);
|
||||
temp_length = htons(len);
|
||||
|
||||
uint32_t current = 0;
|
||||
|
||||
current = ip_checksum_add(current, &(ip->saddr), sizeof(uint32_t));
|
||||
current = ip_checksum_add(current, &(ip->daddr), sizeof(uint32_t));
|
||||
current = ip_checksum_add(current, &temp_protocol, sizeof(uint16_t));
|
||||
|
|
@ -123,15 +123,15 @@ uint32_t ipv4_pseudo_header_checksum(const struct iphdr *ip, uint16_t len) {
|
|||
|
||||
/* function: ip_checksum_adjust
|
||||
* calculates a new checksum given a previous checksum and the old and new pseudo-header checksums
|
||||
* checksum - the header checksum in the original packet in network byte order
|
||||
* old_hdr_sum - the pseudo-header checksum of the original packet
|
||||
* new_hdr_sum - the pseudo-header checksum of the translated packet
|
||||
* returns: the new header checksum in network byte order
|
||||
* checksum - the header checksum in the original packet in network byte order
|
||||
* old_hdr_sum - the pseudo-header checksum of the original packet
|
||||
* new_hdr_sum - the pseudo-header checksum of the translated packet
|
||||
* returns: the new header checksum in network byte order
|
||||
*/
|
||||
uint16_t ip_checksum_adjust(uint16_t checksum, uint32_t old_hdr_sum, uint32_t new_hdr_sum) {
|
||||
// Algorithm suggested in RFC 1624.
|
||||
// http://tools.ietf.org/html/rfc1624#section-3
|
||||
checksum = ~checksum;
|
||||
checksum = ~checksum;
|
||||
uint16_t folded_sum = ip_checksum_fold(checksum + new_hdr_sum);
|
||||
uint16_t folded_old = ip_checksum_fold(old_hdr_sum);
|
||||
if (folded_sum > folded_old) {
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@
|
|||
#ifndef __CHECKSUM_H__
|
||||
#define __CHECKSUM_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t ip_checksum_add(uint32_t current, const void *data, int len);
|
||||
uint16_t ip_checksum_finish(uint32_t temp_sum);
|
||||
|
|
|
|||
209
clatd.c
209
clatd.c
|
|
@ -15,43 +15,43 @@
|
|||
*
|
||||
* clatd.c - tun interface setup and main event loop
|
||||
*/
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <sys/capability.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/capability.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <private/android_filesystem_config.h>
|
||||
|
||||
#include "translate.h"
|
||||
#include "clatd.h"
|
||||
#include "config.h"
|
||||
#include "logging.h"
|
||||
#include "resolv_netid.h"
|
||||
#include "setif.h"
|
||||
#include "mtu.h"
|
||||
#include "getaddr.h"
|
||||
#include "dump.h"
|
||||
#include "tun.h"
|
||||
#include "getaddr.h"
|
||||
#include "logging.h"
|
||||
#include "mtu.h"
|
||||
#include "resolv_netid.h"
|
||||
#include "ring.h"
|
||||
#include "setif.h"
|
||||
#include "translate.h"
|
||||
#include "tun.h"
|
||||
|
||||
#define DEVICEPREFIX "v4-"
|
||||
|
||||
|
|
@ -63,13 +63,11 @@ volatile sig_atomic_t running = 1;
|
|||
/* function: stop_loop
|
||||
* signal handler: stop the event loop
|
||||
*/
|
||||
void stop_loop() {
|
||||
running = 0;
|
||||
}
|
||||
void stop_loop() { running = 0; }
|
||||
|
||||
/* function: configure_packet_socket
|
||||
* Binds the packet socket and attaches the receive filter to it.
|
||||
* sock - the socket to configure
|
||||
* sock - the socket to configure
|
||||
*/
|
||||
int configure_packet_socket(int sock) {
|
||||
struct sockaddr_ll sll = {
|
||||
|
|
@ -78,12 +76,14 @@ int configure_packet_socket(int sock) {
|
|||
.sll_ifindex = if_nametoindex(Global_Clatd_Config.default_pdp_interface),
|
||||
.sll_pkttype = PACKET_OTHERHOST, // The 464xlat IPv6 address is not assigned to the kernel.
|
||||
};
|
||||
if (bind(sock, (struct sockaddr *) &sll, sizeof(sll))) {
|
||||
if (bind(sock, (struct sockaddr *)&sll, sizeof(sll))) {
|
||||
logmsg(ANDROID_LOG_FATAL, "binding packet socket: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t *ipv6 = Global_Clatd_Config.ipv6_local_subnet.s6_addr32;
|
||||
|
||||
// clang-format off
|
||||
struct sock_filter filter_code[] = {
|
||||
// Load the first four bytes of the IPv6 destination address (starts 24 bytes in).
|
||||
// Compare it against the first four bytes of our IPv6 address, in host byte order (BPF loads
|
||||
|
|
@ -99,12 +99,10 @@ int configure_packet_socket(int sock) {
|
|||
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, 36),
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, htonl(ipv6[3]), 0, 1),
|
||||
BPF_STMT(BPF_RET | BPF_K, PACKETLEN),
|
||||
BPF_STMT(BPF_RET | BPF_K, 0)
|
||||
};
|
||||
struct sock_fprog filter = {
|
||||
sizeof(filter_code) / sizeof(filter_code[0]),
|
||||
filter_code
|
||||
BPF_STMT(BPF_RET | BPF_K, 0),
|
||||
};
|
||||
// clang-format on
|
||||
struct sock_fprog filter = { sizeof(filter_code) / sizeof(filter_code[0]), filter_code };
|
||||
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter))) {
|
||||
logmsg(ANDROID_LOG_FATAL, "attach packet filter failed: %s", strerror(errno));
|
||||
|
|
@ -116,7 +114,7 @@ int configure_packet_socket(int sock) {
|
|||
|
||||
/* function: configure_tun_ip
|
||||
* configures the ipv4 and ipv6 addresses on the tunnel interface
|
||||
* tunnel - tun device data
|
||||
* tunnel - tun device data
|
||||
*/
|
||||
void configure_tun_ip(const struct tun_data *tunnel) {
|
||||
int status;
|
||||
|
|
@ -130,7 +128,7 @@ void configure_tun_ip(const struct tun_data *tunnel) {
|
|||
in_addr_t localaddr = config_select_ipv4_address(&Global_Clatd_Config.ipv4_local_subnet,
|
||||
Global_Clatd_Config.ipv4_local_prefixlen);
|
||||
if (localaddr == INADDR_NONE) {
|
||||
logmsg(ANDROID_LOG_FATAL,"No free IPv4 address in %s/%d",
|
||||
logmsg(ANDROID_LOG_FATAL, "No free IPv4 address in %s/%d",
|
||||
inet_ntoa(Global_Clatd_Config.ipv4_local_subnet),
|
||||
Global_Clatd_Config.ipv4_local_prefixlen);
|
||||
exit(1);
|
||||
|
|
@ -139,10 +137,10 @@ void configure_tun_ip(const struct tun_data *tunnel) {
|
|||
|
||||
// Configure the interface before bringing it up. As soon as we bring the interface up, the
|
||||
// framework will be notified and will assume the interface's configuration has been finalized.
|
||||
status = add_address(tunnel->device4, AF_INET, &Global_Clatd_Config.ipv4_local_subnet,
|
||||
32, &Global_Clatd_Config.ipv4_local_subnet);
|
||||
if(status < 0) {
|
||||
logmsg(ANDROID_LOG_FATAL,"configure_tun_ip/if_address(4) failed: %s",strerror(-status));
|
||||
status = add_address(tunnel->device4, AF_INET, &Global_Clatd_Config.ipv4_local_subnet, 32,
|
||||
&Global_Clatd_Config.ipv4_local_subnet);
|
||||
if (status < 0) {
|
||||
logmsg(ANDROID_LOG_FATAL, "configure_tun_ip/if_address(4) failed: %s", strerror(-status));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
|
@ -150,8 +148,8 @@ void configure_tun_ip(const struct tun_data *tunnel) {
|
|||
inet_ntop(AF_INET, &Global_Clatd_Config.ipv4_local_subnet, addrstr, sizeof(addrstr));
|
||||
logmsg(ANDROID_LOG_INFO, "Using IPv4 address %s on %s", addrstr, tunnel->device4);
|
||||
|
||||
if((status = if_up(tunnel->device4, Global_Clatd_Config.ipv4mtu)) < 0) {
|
||||
logmsg(ANDROID_LOG_FATAL,"configure_tun_ip/if_up(4) failed: %s",strerror(-status));
|
||||
if ((status = if_up(tunnel->device4, Global_Clatd_Config.ipv4mtu)) < 0) {
|
||||
logmsg(ANDROID_LOG_FATAL, "configure_tun_ip/if_up(4) failed: %s", strerror(-status));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
|
@ -161,19 +159,19 @@ void configure_tun_ip(const struct tun_data *tunnel) {
|
|||
*/
|
||||
void drop_root() {
|
||||
gid_t groups[] = { AID_INET, AID_VPN };
|
||||
if(setgroups(sizeof(groups)/sizeof(groups[0]), groups) < 0) {
|
||||
logmsg(ANDROID_LOG_FATAL,"drop_root/setgroups failed: %s",strerror(errno));
|
||||
if (setgroups(sizeof(groups) / sizeof(groups[0]), groups) < 0) {
|
||||
logmsg(ANDROID_LOG_FATAL, "drop_root/setgroups failed: %s", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
|
||||
|
||||
if(setgid(AID_CLAT) < 0) {
|
||||
logmsg(ANDROID_LOG_FATAL,"drop_root/setgid failed: %s",strerror(errno));
|
||||
if (setgid(AID_CLAT) < 0) {
|
||||
logmsg(ANDROID_LOG_FATAL, "drop_root/setgid failed: %s", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
if(setuid(AID_CLAT) < 0) {
|
||||
logmsg(ANDROID_LOG_FATAL,"drop_root/setuid failed: %s",strerror(errno));
|
||||
if (setuid(AID_CLAT) < 0) {
|
||||
logmsg(ANDROID_LOG_FATAL, "drop_root/setuid failed: %s", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
|
@ -183,19 +181,19 @@ void drop_root() {
|
|||
memset(&cap, 0, sizeof(cap));
|
||||
|
||||
header.version = _LINUX_CAPABILITY_VERSION;
|
||||
header.pid = 0; // 0 = change myself
|
||||
header.pid = 0; // 0 = change myself
|
||||
cap.effective = cap.permitted = (1 << CAP_NET_ADMIN);
|
||||
|
||||
if(capset(&header, &cap) < 0) {
|
||||
logmsg(ANDROID_LOG_FATAL,"drop_root/capset failed: %s",strerror(errno));
|
||||
if (capset(&header, &cap) < 0) {
|
||||
logmsg(ANDROID_LOG_FATAL, "drop_root/capset failed: %s", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* function: open_sockets
|
||||
* opens a packet socket to receive IPv6 packets and a raw socket to send them
|
||||
* tunnel - tun device data
|
||||
* mark - the socket mark to use for the sending raw socket
|
||||
* tunnel - tun device data
|
||||
* mark - the socket mark to use for the sending raw socket
|
||||
*/
|
||||
void open_sockets(struct tun_data *tunnel, uint32_t mark) {
|
||||
int rawsock = socket(AF_INET6, SOCK_RAW | SOCK_NONBLOCK, IPPROTO_RAW);
|
||||
|
|
@ -222,9 +220,9 @@ void open_sockets(struct tun_data *tunnel, uint32_t mark) {
|
|||
|
||||
/* function: update_clat_ipv6_address
|
||||
* picks the clat IPv6 address and configures packet translation to use it.
|
||||
* tunnel - tun device data
|
||||
* interface - uplink interface name
|
||||
* returns: 1 on success, 0 on failure
|
||||
* tunnel - tun device data
|
||||
* interface - uplink interface name
|
||||
* returns: 1 on success, 0 on failure
|
||||
*/
|
||||
int update_clat_ipv6_address(const struct tun_data *tunnel, const char *interface) {
|
||||
union anyip *interface_ip;
|
||||
|
|
@ -266,9 +264,9 @@ int update_clat_ipv6_address(const struct tun_data *tunnel, const char *interfac
|
|||
|
||||
// Update our packet socket filter to reflect the new 464xlat IP address.
|
||||
if (!configure_packet_socket(tunnel->read_fd6)) {
|
||||
// Things aren't going to work. Bail out and hope we have better luck next time.
|
||||
// We don't log an error here because configure_packet_socket has already done so.
|
||||
exit(1);
|
||||
// Things aren't going to work. Bail out and hope we have better luck next time.
|
||||
// We don't log an error here because configure_packet_socket has already done so.
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
@ -276,41 +274,42 @@ int update_clat_ipv6_address(const struct tun_data *tunnel, const char *interfac
|
|||
|
||||
/* function: configure_interface
|
||||
* reads the configuration and applies it to the interface
|
||||
* uplink_interface - network interface to use to reach the ipv6 internet
|
||||
* plat_prefix - PLAT prefix to use
|
||||
* tunnel - tun device data
|
||||
* net_id - NetID to use, NETID_UNSET indicates use of default network
|
||||
* uplink_interface - network interface to use to reach the ipv6 internet
|
||||
* plat_prefix - PLAT prefix to use
|
||||
* tunnel - tun device data
|
||||
* net_id - NetID to use, NETID_UNSET indicates use of default network
|
||||
*/
|
||||
void configure_interface(const char *uplink_interface, const char *plat_prefix, struct tun_data *tunnel, unsigned net_id) {
|
||||
void configure_interface(const char *uplink_interface, const char *plat_prefix,
|
||||
struct tun_data *tunnel, unsigned net_id) {
|
||||
int error;
|
||||
|
||||
if(!read_config("/system/etc/clatd.conf", uplink_interface, plat_prefix, net_id)) {
|
||||
logmsg(ANDROID_LOG_FATAL,"read_config failed");
|
||||
if (!read_config("/system/etc/clatd.conf", uplink_interface, plat_prefix, net_id)) {
|
||||
logmsg(ANDROID_LOG_FATAL, "read_config failed");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(Global_Clatd_Config.mtu > MAXMTU) {
|
||||
logmsg(ANDROID_LOG_WARN,"Max MTU is %d, requested %d", MAXMTU, Global_Clatd_Config.mtu);
|
||||
if (Global_Clatd_Config.mtu > MAXMTU) {
|
||||
logmsg(ANDROID_LOG_WARN, "Max MTU is %d, requested %d", MAXMTU, Global_Clatd_Config.mtu);
|
||||
Global_Clatd_Config.mtu = MAXMTU;
|
||||
}
|
||||
if(Global_Clatd_Config.mtu <= 0) {
|
||||
if (Global_Clatd_Config.mtu <= 0) {
|
||||
Global_Clatd_Config.mtu = getifmtu(Global_Clatd_Config.default_pdp_interface);
|
||||
logmsg(ANDROID_LOG_WARN,"ifmtu=%d",Global_Clatd_Config.mtu);
|
||||
logmsg(ANDROID_LOG_WARN, "ifmtu=%d", Global_Clatd_Config.mtu);
|
||||
}
|
||||
if(Global_Clatd_Config.mtu < 1280) {
|
||||
logmsg(ANDROID_LOG_WARN,"mtu too small = %d", Global_Clatd_Config.mtu);
|
||||
if (Global_Clatd_Config.mtu < 1280) {
|
||||
logmsg(ANDROID_LOG_WARN, "mtu too small = %d", Global_Clatd_Config.mtu);
|
||||
Global_Clatd_Config.mtu = 1280;
|
||||
}
|
||||
|
||||
if(Global_Clatd_Config.ipv4mtu <= 0 ||
|
||||
Global_Clatd_Config.ipv4mtu > Global_Clatd_Config.mtu - MTU_DELTA) {
|
||||
if (Global_Clatd_Config.ipv4mtu <= 0 ||
|
||||
Global_Clatd_Config.ipv4mtu > Global_Clatd_Config.mtu - MTU_DELTA) {
|
||||
Global_Clatd_Config.ipv4mtu = Global_Clatd_Config.mtu - MTU_DELTA;
|
||||
logmsg(ANDROID_LOG_WARN,"ipv4mtu now set to = %d",Global_Clatd_Config.ipv4mtu);
|
||||
logmsg(ANDROID_LOG_WARN, "ipv4mtu now set to = %d", Global_Clatd_Config.ipv4mtu);
|
||||
}
|
||||
|
||||
error = tun_alloc(tunnel->device4, tunnel->fd4);
|
||||
if(error < 0) {
|
||||
logmsg(ANDROID_LOG_FATAL,"tun_alloc/4 failed: %s",strerror(errno));
|
||||
if (error < 0) {
|
||||
logmsg(ANDROID_LOG_FATAL, "tun_alloc/4 failed: %s", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
|
@ -325,9 +324,9 @@ void configure_interface(const char *uplink_interface, const char *plat_prefix,
|
|||
|
||||
/* function: read_packet
|
||||
* reads a packet from the tunnel fd and translates it
|
||||
* read_fd - file descriptor to read original packet from
|
||||
* write_fd - file descriptor to write translated packet to
|
||||
* to_ipv6 - whether the packet is to be translated to ipv6 or ipv4
|
||||
* read_fd - file descriptor to read original packet from
|
||||
* write_fd - file descriptor to write translated packet to
|
||||
* to_ipv6 - whether the packet is to be translated to ipv6 or ipv4
|
||||
*/
|
||||
void read_packet(int read_fd, int write_fd, int to_ipv6) {
|
||||
ssize_t readlen;
|
||||
|
|
@ -335,20 +334,20 @@ void read_packet(int read_fd, int write_fd, int to_ipv6) {
|
|||
|
||||
readlen = read(read_fd, buf, PACKETLEN);
|
||||
|
||||
if(readlen < 0) {
|
||||
if (readlen < 0) {
|
||||
if (errno != EAGAIN) {
|
||||
logmsg(ANDROID_LOG_WARN,"read_packet/read error: %s", strerror(errno));
|
||||
logmsg(ANDROID_LOG_WARN, "read_packet/read error: %s", strerror(errno));
|
||||
}
|
||||
return;
|
||||
} else if(readlen == 0) {
|
||||
logmsg(ANDROID_LOG_WARN,"read_packet/tun interface removed");
|
||||
} else if (readlen == 0) {
|
||||
logmsg(ANDROID_LOG_WARN, "read_packet/tun interface removed");
|
||||
running = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
struct tun_pi *tun_header = (struct tun_pi *) buf;
|
||||
if (readlen < (ssize_t) sizeof(*tun_header)) {
|
||||
logmsg(ANDROID_LOG_WARN,"read_packet/short read: got %ld bytes", readlen);
|
||||
struct tun_pi *tun_header = (struct tun_pi *)buf;
|
||||
if (readlen < (ssize_t)sizeof(*tun_header)) {
|
||||
logmsg(ANDROID_LOG_WARN, "read_packet/short read: got %ld bytes", readlen);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -358,18 +357,18 @@ void read_packet(int read_fd, int write_fd, int to_ipv6) {
|
|||
return;
|
||||
}
|
||||
|
||||
if(tun_header->flags != 0) {
|
||||
if (tun_header->flags != 0) {
|
||||
logmsg(ANDROID_LOG_WARN, "%s: unexpected flags = %d", __func__, tun_header->flags);
|
||||
}
|
||||
|
||||
packet = (uint8_t *) (tun_header + 1);
|
||||
packet = (uint8_t *)(tun_header + 1);
|
||||
readlen -= sizeof(*tun_header);
|
||||
translate_packet(write_fd, to_ipv6, packet, readlen);
|
||||
}
|
||||
|
||||
/* function: event_loop
|
||||
* reads packets from the tun network interface and passes them down the stack
|
||||
* tunnel - tun device data
|
||||
* tunnel - tun device data
|
||||
*/
|
||||
void event_loop(struct tun_data *tunnel) {
|
||||
time_t last_interface_poll;
|
||||
|
|
@ -381,11 +380,10 @@ void event_loop(struct tun_data *tunnel) {
|
|||
// start the poll timer
|
||||
last_interface_poll = time(NULL);
|
||||
|
||||
while(running) {
|
||||
if (poll(wait_fd, ARRAY_SIZE(wait_fd),
|
||||
NO_TRAFFIC_INTERFACE_POLL_FREQUENCY * 1000) == -1) {
|
||||
while (running) {
|
||||
if (poll(wait_fd, ARRAY_SIZE(wait_fd), NO_TRAFFIC_INTERFACE_POLL_FREQUENCY * 1000) == -1) {
|
||||
if (errno != EINTR) {
|
||||
logmsg(ANDROID_LOG_WARN,"event_loop/poll returned an error: %s", strerror(errno));
|
||||
logmsg(ANDROID_LOG_WARN, "event_loop/poll returned an error: %s", strerror(errno));
|
||||
}
|
||||
} else {
|
||||
if (wait_fd[0].revents & POLLIN) {
|
||||
|
|
@ -395,8 +393,7 @@ void event_loop(struct tun_data *tunnel) {
|
|||
if (wait_fd[0].revents & ~POLLIN) {
|
||||
// ring_read doesn't clear the error indication on the socket.
|
||||
recv(tunnel->read_fd6, NULL, 0, MSG_PEEK);
|
||||
logmsg(ANDROID_LOG_WARN, "event_loop: clearing error on read_fd6: %s",
|
||||
strerror(errno));
|
||||
logmsg(ANDROID_LOG_WARN, "event_loop: clearing error on read_fd6: %s", strerror(errno));
|
||||
}
|
||||
|
||||
// Call read_packet if the socket has data to be read, but also if an
|
||||
|
|
@ -410,7 +407,7 @@ void event_loop(struct tun_data *tunnel) {
|
|||
}
|
||||
|
||||
time_t now = time(NULL);
|
||||
if(last_interface_poll < (now - INTERFACE_POLL_FREQUENCY)) {
|
||||
if (last_interface_poll < (now - INTERFACE_POLL_FREQUENCY)) {
|
||||
update_clat_ipv6_address(tunnel, Global_Clatd_Config.default_pdp_interface);
|
||||
last_interface_poll = now;
|
||||
}
|
||||
|
|
@ -430,13 +427,13 @@ void print_help() {
|
|||
|
||||
/* function: parse_unsigned
|
||||
* parses a string as a decimal/hex/octal unsigned integer
|
||||
* str - the string to parse
|
||||
* out - the unsigned integer to write to, gets clobbered on failure
|
||||
* str - the string to parse
|
||||
* out - the unsigned integer to write to, gets clobbered on failure
|
||||
*/
|
||||
int parse_unsigned(const char *str, unsigned *out) {
|
||||
char *end_ptr;
|
||||
*out = strtoul(str, &end_ptr, 0);
|
||||
return *str && !*end_ptr;
|
||||
char *end_ptr;
|
||||
*out = strtoul(str, &end_ptr, 0);
|
||||
return *str && !*end_ptr;
|
||||
}
|
||||
|
||||
/* function: main
|
||||
|
|
@ -447,11 +444,11 @@ int main(int argc, char **argv) {
|
|||
int opt;
|
||||
char *uplink_interface = NULL, *plat_prefix = NULL, *net_id_str = NULL, *mark_str = NULL;
|
||||
unsigned net_id = NETID_UNSET;
|
||||
uint32_t mark = MARK_UNSET;
|
||||
uint32_t mark = MARK_UNSET;
|
||||
unsigned len;
|
||||
|
||||
while((opt = getopt(argc, argv, "i:p:n:m:h")) != -1) {
|
||||
switch(opt) {
|
||||
while ((opt = getopt(argc, argv, "i:p:n:m:h")) != -1) {
|
||||
switch (opt) {
|
||||
case 'i':
|
||||
uplink_interface = optarg;
|
||||
break;
|
||||
|
|
@ -468,12 +465,12 @@ int main(int argc, char **argv) {
|
|||
print_help();
|
||||
exit(0);
|
||||
default:
|
||||
logmsg(ANDROID_LOG_FATAL, "Unknown option -%c. Exiting.", (char) optopt);
|
||||
logmsg(ANDROID_LOG_FATAL, "Unknown option -%c. Exiting.", (char)optopt);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if(uplink_interface == NULL) {
|
||||
if (uplink_interface == NULL) {
|
||||
logmsg(ANDROID_LOG_FATAL, "clatd called without an interface");
|
||||
exit(1);
|
||||
}
|
||||
|
|
@ -494,10 +491,8 @@ int main(int argc, char **argv) {
|
|||
exit(1);
|
||||
}
|
||||
|
||||
logmsg(ANDROID_LOG_INFO, "Starting clat version %s on %s netid=%s mark=%s",
|
||||
CLATD_VERSION, uplink_interface,
|
||||
net_id_str ? net_id_str : "(none)",
|
||||
mark_str ? mark_str : "(none)");
|
||||
logmsg(ANDROID_LOG_INFO, "Starting clat version %s on %s netid=%s mark=%s", CLATD_VERSION,
|
||||
uplink_interface, net_id_str ? net_id_str : "(none)", mark_str ? mark_str : "(none)");
|
||||
|
||||
// open our raw sockets before dropping privs
|
||||
open_sockets(&tunnel, mark);
|
||||
|
|
@ -507,7 +502,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
// we can create tun devices as non-root because we're in the VPN group.
|
||||
tunnel.fd4 = tun_open();
|
||||
if(tunnel.fd4 < 0) {
|
||||
if (tunnel.fd4 < 0) {
|
||||
logmsg(ANDROID_LOG_FATAL, "tun_open4 failed: %s", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
|
@ -522,14 +517,14 @@ int main(int argc, char **argv) {
|
|||
update_clat_ipv6_address(&tunnel, uplink_interface);
|
||||
|
||||
// Loop until someone sends us a signal or brings down the tun interface.
|
||||
if(signal(SIGTERM, stop_loop) == SIG_ERR) {
|
||||
if (signal(SIGTERM, stop_loop) == SIG_ERR) {
|
||||
logmsg(ANDROID_LOG_FATAL, "sigterm handler failed: %s", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
event_loop(&tunnel);
|
||||
|
||||
logmsg(ANDROID_LOG_INFO,"Shutting down clat on %s", uplink_interface);
|
||||
logmsg(ANDROID_LOG_INFO, "Shutting down clat on %s", uplink_interface);
|
||||
del_anycast_address(tunnel.write_fd6, &Global_Clatd_Config.ipv6_local_subnet);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
14
clatd.h
14
clatd.h
|
|
@ -21,7 +21,7 @@
|
|||
#include <sys/uio.h>
|
||||
|
||||
#define MAXMTU 1500
|
||||
#define PACKETLEN (MAXMTU+sizeof(struct tun_pi))
|
||||
#define PACKETLEN (MAXMTU + sizeof(struct tun_pi))
|
||||
#define CLATD_VERSION "1.4"
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
|
@ -37,9 +37,15 @@
|
|||
// specific parts of the packet. The packet_* functions operate on all the packet segments past a
|
||||
// given position.
|
||||
typedef enum {
|
||||
CLAT_POS_TUNHDR, CLAT_POS_IPHDR, CLAT_POS_FRAGHDR, CLAT_POS_TRANSPORTHDR,
|
||||
CLAT_POS_ICMPERR_IPHDR, CLAT_POS_ICMPERR_FRAGHDR, CLAT_POS_ICMPERR_TRANSPORTHDR,
|
||||
CLAT_POS_PAYLOAD, CLAT_POS_MAX
|
||||
CLAT_POS_TUNHDR,
|
||||
CLAT_POS_IPHDR,
|
||||
CLAT_POS_FRAGHDR,
|
||||
CLAT_POS_TRANSPORTHDR,
|
||||
CLAT_POS_ICMPERR_IPHDR,
|
||||
CLAT_POS_ICMPERR_FRAGHDR,
|
||||
CLAT_POS_ICMPERR_TRANSPORTHDR,
|
||||
CLAT_POS_PAYLOAD,
|
||||
CLAT_POS_MAX
|
||||
} clat_packet_index;
|
||||
typedef struct iovec clat_packet[CLAT_POS_MAX];
|
||||
|
||||
|
|
|
|||
|
|
@ -21,25 +21,25 @@
|
|||
* adb shell /data/nativetest/clatd_microbenchmark/clatd_microbenchmark
|
||||
*
|
||||
*/
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "checksum.h"
|
||||
#include "tun.h"
|
||||
|
|
@ -52,163 +52,162 @@
|
|||
#define SEC_TO_NANOSEC (1000 * 1000 * 1000)
|
||||
|
||||
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);
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_port = 0;
|
||||
sin->sin_addr.s_addr = inet_addr(addr);
|
||||
}
|
||||
|
||||
void die(const char *str) {
|
||||
perror(str);
|
||||
exit(1);
|
||||
perror(str);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int setup_tun() {
|
||||
int fd = tun_open();
|
||||
if (fd == -1) die("tun_open");
|
||||
int fd = tun_open();
|
||||
if (fd == -1) die("tun_open");
|
||||
|
||||
char dev[IFNAMSIZ] = DEVICENAME;
|
||||
int ret = tun_alloc(dev, fd);
|
||||
if (ret == -1) die("tun_alloc");
|
||||
struct ifreq ifr = {
|
||||
.ifr_name = DEVICENAME,
|
||||
};
|
||||
char dev[IFNAMSIZ] = DEVICENAME;
|
||||
int ret = tun_alloc(dev, fd);
|
||||
if (ret == -1) die("tun_alloc");
|
||||
struct ifreq ifr = {
|
||||
.ifr_name = DEVICENAME,
|
||||
};
|
||||
|
||||
int s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
init_sockaddr_in((struct sockaddr_in *) &ifr.ifr_addr, "192.0.0.4");
|
||||
if (ioctl(s, SIOCSIFADDR, &ifr) < 0) die("SIOCSIFADDR");
|
||||
init_sockaddr_in((struct sockaddr_in *) &ifr.ifr_addr, "255.255.255.248");
|
||||
if (ioctl(s, SIOCSIFNETMASK, &ifr) < 0) die("SIOCSIFNETMASK");
|
||||
if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) die("SIOCGIFFLAGS");
|
||||
ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
|
||||
if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0) die("SIOCSIFFLAGS");
|
||||
return fd;
|
||||
int s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
init_sockaddr_in((struct sockaddr_in *)&ifr.ifr_addr, "192.0.0.4");
|
||||
if (ioctl(s, SIOCSIFADDR, &ifr) < 0) die("SIOCSIFADDR");
|
||||
init_sockaddr_in((struct sockaddr_in *)&ifr.ifr_addr, "255.255.255.248");
|
||||
if (ioctl(s, SIOCSIFNETMASK, &ifr) < 0) die("SIOCSIFNETMASK");
|
||||
if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) die("SIOCGIFFLAGS");
|
||||
ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
|
||||
if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0) die("SIOCSIFFLAGS");
|
||||
return fd;
|
||||
}
|
||||
|
||||
int send_packet(int fd, uint8_t payload[], int len, uint32_t payload_checksum) {
|
||||
struct tun_pi tun = { 0, htons(ETH_P_IP) };
|
||||
struct udphdr udp = {
|
||||
.source = htons(1234),
|
||||
.dest = htons(PORT),
|
||||
.len = htons(len + sizeof(udp)),
|
||||
.check = 0,
|
||||
};
|
||||
struct iphdr ip = {
|
||||
.version = 4,
|
||||
.ihl = 5,
|
||||
.tot_len = htons(len + sizeof(ip) + sizeof(udp)),
|
||||
.frag_off = htons(IP_DF),
|
||||
.ttl = 55,
|
||||
.protocol = IPPROTO_UDP,
|
||||
.saddr = htonl(0xc0000006), // 192.0.0.6
|
||||
.daddr = htonl(0xc0000004), // 192.0.0.4
|
||||
};
|
||||
clat_packet out = {
|
||||
{ &tun, sizeof(tun) }, // tun header
|
||||
{ &ip, sizeof(ip) }, // IP header
|
||||
{ NULL, 0 }, // Fragment header
|
||||
{ &udp, sizeof(udp) }, // Transport header
|
||||
{ NULL, 0 }, // ICMP error IP header
|
||||
{ NULL, 0 }, // ICMP error fragment header
|
||||
{ NULL, 0 }, // ICMP error transport header
|
||||
{ payload, len }, // Payload
|
||||
};
|
||||
struct tun_pi tun = { 0, htons(ETH_P_IP) };
|
||||
struct udphdr udp = {
|
||||
.source = htons(1234),
|
||||
.dest = htons(PORT),
|
||||
.len = htons(len + sizeof(udp)),
|
||||
.check = 0,
|
||||
};
|
||||
struct iphdr ip = {
|
||||
.version = 4,
|
||||
.ihl = 5,
|
||||
.tot_len = htons(len + sizeof(ip) + sizeof(udp)),
|
||||
.frag_off = htons(IP_DF),
|
||||
.ttl = 55,
|
||||
.protocol = IPPROTO_UDP,
|
||||
.saddr = htonl(0xc0000006), // 192.0.0.6
|
||||
.daddr = htonl(0xc0000004), // 192.0.0.4
|
||||
};
|
||||
clat_packet out = {
|
||||
{ &tun, sizeof(tun) }, // tun header
|
||||
{ &ip, sizeof(ip) }, // IP header
|
||||
{ NULL, 0 }, // Fragment header
|
||||
{ &udp, sizeof(udp) }, // Transport header
|
||||
{ NULL, 0 }, // ICMP error IP header
|
||||
{ NULL, 0 }, // ICMP error fragment header
|
||||
{ NULL, 0 }, // ICMP error transport header
|
||||
{ payload, len }, // Payload
|
||||
};
|
||||
|
||||
ip.check = ip_checksum(&ip, sizeof(ip));
|
||||
ip.check = ip_checksum(&ip, sizeof(ip));
|
||||
|
||||
uint32_t sum;
|
||||
sum = ipv4_pseudo_header_checksum(&ip, ntohs(udp.len));
|
||||
sum = ip_checksum_add(sum, &udp, sizeof(udp));
|
||||
sum += payload_checksum;
|
||||
udp.check = ip_checksum_finish(sum);
|
||||
uint32_t sum;
|
||||
sum = ipv4_pseudo_header_checksum(&ip, ntohs(udp.len));
|
||||
sum = ip_checksum_add(sum, &udp, sizeof(udp));
|
||||
sum += payload_checksum;
|
||||
udp.check = ip_checksum_finish(sum);
|
||||
|
||||
return send_tun(fd, out, sizeof(out) / sizeof(out[0]));
|
||||
return send_tun(fd, out, sizeof(out) / sizeof(out[0]));
|
||||
}
|
||||
|
||||
double timedelta(const struct timespec tv1, const struct timespec tv2) {
|
||||
struct timespec end = tv2;
|
||||
if (end.tv_nsec < tv1.tv_nsec) {
|
||||
end.tv_sec -= 1;
|
||||
end.tv_nsec += SEC_TO_NANOSEC;
|
||||
}
|
||||
double seconds = (end.tv_sec - tv1.tv_sec);
|
||||
seconds += (((double) (end.tv_nsec - tv1.tv_nsec)) / SEC_TO_NANOSEC);
|
||||
return seconds;
|
||||
struct timespec end = tv2;
|
||||
if (end.tv_nsec < tv1.tv_nsec) {
|
||||
end.tv_sec -= 1;
|
||||
end.tv_nsec += SEC_TO_NANOSEC;
|
||||
}
|
||||
double seconds = (end.tv_sec - tv1.tv_sec);
|
||||
seconds += (((double)(end.tv_nsec - tv1.tv_nsec)) / SEC_TO_NANOSEC);
|
||||
return seconds;
|
||||
}
|
||||
|
||||
void benchmark(const char *name, int fd, int s, int num, int do_read,
|
||||
uint8_t payload[], int len, uint32_t payload_sum) {
|
||||
int i;
|
||||
char buf[4096];
|
||||
struct timespec tv1, tv2;
|
||||
int write_err = 0, read_err = 0;
|
||||
clock_gettime(CLOCK_MONOTONIC, &tv1);
|
||||
for (i = 0; i < num; i++) {
|
||||
if (send_packet(fd, payload, len, payload_sum) == -1) write_err++;
|
||||
if (do_read && recvfrom(s, buf, sizeof(buf), 0, NULL, NULL) == -1) {
|
||||
read_err++;
|
||||
if (errno == ETIMEDOUT) {
|
||||
printf("Timed out after %d packets!\n", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
void benchmark(const char *name, int fd, int s, int num, int do_read, uint8_t payload[], int len,
|
||||
uint32_t payload_sum) {
|
||||
int i;
|
||||
char buf[4096];
|
||||
struct timespec tv1, tv2;
|
||||
int write_err = 0, read_err = 0;
|
||||
clock_gettime(CLOCK_MONOTONIC, &tv1);
|
||||
for (i = 0; i < num; i++) {
|
||||
if (send_packet(fd, payload, len, payload_sum) == -1) write_err++;
|
||||
if (do_read && recvfrom(s, buf, sizeof(buf), 0, NULL, NULL) == -1) {
|
||||
read_err++;
|
||||
if (errno == ETIMEDOUT) {
|
||||
printf("Timed out after %d packets!\n", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
clock_gettime(CLOCK_MONOTONIC, &tv2);
|
||||
double seconds = timedelta(tv1, tv2);
|
||||
int pps = (int) (i / seconds);
|
||||
double mbps = (i * PAYLOADSIZE / 1000000 * 8 / seconds);
|
||||
printf("%s: %d packets in %.2fs (%d pps, %.2f Mbps), ", name, i, seconds, pps, mbps);
|
||||
printf("read err %d (%.2f%%), write err %d (%.2f%%)\n",
|
||||
read_err, (float) read_err / i * 100,
|
||||
write_err, (float) write_err / i * 100);
|
||||
}
|
||||
clock_gettime(CLOCK_MONOTONIC, &tv2);
|
||||
double seconds = timedelta(tv1, tv2);
|
||||
int pps = (int)(i / seconds);
|
||||
double mbps = (i * PAYLOADSIZE / 1000000 * 8 / seconds);
|
||||
printf("%s: %d packets in %.2fs (%d pps, %.2f Mbps), ", name, i, seconds, pps, mbps);
|
||||
printf("read err %d (%.2f%%), write err %d (%.2f%%)\n", read_err, (float)read_err / i * 100,
|
||||
write_err, (float)write_err / i * 100);
|
||||
}
|
||||
|
||||
int open_socket() {
|
||||
int sock = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
|
||||
int sock = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
|
||||
|
||||
int on = 1;
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) die("SO_REUSEADDR");
|
||||
int on = 1;
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) die("SO_REUSEADDR");
|
||||
|
||||
struct timeval tv = { 1, 0 };
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) die("SO_RCVTIMEO");
|
||||
struct timeval tv = { 1, 0 };
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) die("SO_RCVTIMEO");
|
||||
|
||||
struct sockaddr_in addr = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = ntohs(PORT),
|
||||
.sin_addr = { INADDR_ANY }
|
||||
};
|
||||
if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) == -1) die ("bind");
|
||||
struct sockaddr_in addr = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = ntohs(PORT),
|
||||
.sin_addr = { INADDR_ANY },
|
||||
};
|
||||
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) die("bind");
|
||||
|
||||
return sock;
|
||||
return sock;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int fd = setup_tun();
|
||||
int sock = open_socket();
|
||||
int fd = setup_tun();
|
||||
int sock = open_socket();
|
||||
|
||||
int i;
|
||||
uint8_t payload[PAYLOADSIZE];
|
||||
for (i = 0; i < (int) sizeof(payload); i++) {
|
||||
payload[i] = (uint8_t) i;
|
||||
}
|
||||
uint32_t payload_sum = ip_checksum_add(0, payload, sizeof(payload));
|
||||
int i;
|
||||
uint8_t payload[PAYLOADSIZE];
|
||||
for (i = 0; i < (int)sizeof(payload); i++) {
|
||||
payload[i] = (uint8_t)i;
|
||||
}
|
||||
uint32_t payload_sum = ip_checksum_add(0, payload, sizeof(payload));
|
||||
|
||||
// Check things are working.
|
||||
char buf[4096];
|
||||
if (send_packet(fd, payload, sizeof(payload), payload_sum) == -1) die("send_packet");
|
||||
if (recvfrom(sock, buf, sizeof(buf), 0, NULL, NULL) == -1) die("recvfrom");
|
||||
// Check things are working.
|
||||
char buf[4096];
|
||||
if (send_packet(fd, payload, sizeof(payload), payload_sum) == -1) die("send_packet");
|
||||
if (recvfrom(sock, buf, sizeof(buf), 0, NULL, NULL) == -1) die("recvfrom");
|
||||
|
||||
benchmark("Blocking", fd, sock, NUMPACKETS, 1, payload, sizeof(payload), payload_sum);
|
||||
close(fd);
|
||||
benchmark("Blocking", fd, sock, NUMPACKETS, 1, payload, sizeof(payload), payload_sum);
|
||||
close(fd);
|
||||
|
||||
fd = setup_tun();
|
||||
set_nonblocking(fd);
|
||||
benchmark("No read", fd, sock, NUMPACKETS, 0, payload, sizeof(payload), payload_sum);
|
||||
close(fd);
|
||||
fd = setup_tun();
|
||||
set_nonblocking(fd);
|
||||
benchmark("No read", fd, sock, NUMPACKETS, 0, payload, sizeof(payload), payload_sum);
|
||||
close(fd);
|
||||
|
||||
fd = setup_tun();
|
||||
set_nonblocking(fd);
|
||||
benchmark("Nonblocking", fd, sock, NUMPACKETS, 1, payload, sizeof(payload), payload_sum);
|
||||
close(fd);
|
||||
fd = setup_tun();
|
||||
set_nonblocking(fd);
|
||||
benchmark("Nonblocking", fd, sock, NUMPACKETS, 1, payload, sizeof(payload), payload_sum);
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
236
clatd_test.cpp
236
clatd_test.cpp
|
|
@ -18,28 +18,29 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in6.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
extern "C" {
|
||||
#include "checksum.h"
|
||||
#include "translate.h"
|
||||
#include "config.h"
|
||||
#include "clatd.h"
|
||||
#include "config.h"
|
||||
#include "translate.h"
|
||||
}
|
||||
|
||||
// For convenience.
|
||||
#define ARRAYSIZE(x) sizeof((x)) / sizeof((x)[0])
|
||||
|
||||
// Default translation parameters.
|
||||
static const char kIPv4LocalAddr[] = "192.0.0.4";
|
||||
static const char kIPv6LocalAddr[] = "2001:db8:0:b11::464";
|
||||
static const char kIPv4LocalAddr[] = "192.0.0.4";
|
||||
static const char kIPv6LocalAddr[] = "2001:db8:0:b11::464";
|
||||
static const char kIPv6PlatSubnet[] = "64:ff9b::";
|
||||
|
||||
// clang-format off
|
||||
// Test packet portions. Defined as macros because it's easy to concatenate them to make packets.
|
||||
#define IPV4_HEADER(p, c1, c2) \
|
||||
0x45, 0x00, 0, 41, /* Version=4, IHL=5, ToS=0x80, len=41 */ \
|
||||
|
|
@ -164,6 +165,7 @@ static const uint8_t kReassembledIPv4[] = {
|
|||
0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
|
||||
0x01
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
// Expected checksums.
|
||||
static const uint32_t kUdpPartialChecksum = 0xd5c8;
|
||||
|
|
@ -185,9 +187,9 @@ int is_ipv6_fragment(struct ip6_hdr *ip6, size_t len) {
|
|||
if (ip6->ip6_nxt != IPPROTO_FRAGMENT) {
|
||||
return 0;
|
||||
}
|
||||
struct ip6_frag *frag = (struct ip6_frag *) (ip6 + 1);
|
||||
struct ip6_frag *frag = (struct ip6_frag *)(ip6 + 1);
|
||||
return len >= sizeof(*ip6) + sizeof(*frag) &&
|
||||
(frag->ip6f_offlg & (IP6F_OFF_MASK | IP6F_MORE_FRAG));
|
||||
(frag->ip6f_offlg & (IP6F_OFF_MASK | IP6F_MORE_FRAG));
|
||||
}
|
||||
|
||||
int ipv4_fragment_offset(struct iphdr *ip) {
|
||||
|
|
@ -200,50 +202,50 @@ int ipv6_fragment_offset(struct ip6_frag *frag) {
|
|||
|
||||
void check_packet(const uint8_t *packet, size_t len, const char *msg) {
|
||||
void *payload;
|
||||
size_t payload_length = 0;
|
||||
size_t payload_length = 0;
|
||||
uint32_t pseudo_checksum = 0;
|
||||
uint8_t protocol = 0;
|
||||
int version = ip_version(packet);
|
||||
uint8_t protocol = 0;
|
||||
int version = ip_version(packet);
|
||||
switch (version) {
|
||||
case 4: {
|
||||
struct iphdr *ip = (struct iphdr *) packet;
|
||||
struct iphdr *ip = (struct iphdr *)packet;
|
||||
ASSERT_GE(len, sizeof(*ip)) << msg << ": IPv4 packet shorter than IPv4 header\n";
|
||||
EXPECT_EQ(5, ip->ihl) << msg << ": Unsupported IP header length\n";
|
||||
EXPECT_EQ(len, ntohs(ip->tot_len)) << msg << ": Incorrect IPv4 length\n";
|
||||
EXPECT_EQ(0, ip_checksum(ip, sizeof(*ip))) << msg << ": Incorrect IP checksum\n";
|
||||
protocol = ip->protocol;
|
||||
payload = ip + 1;
|
||||
payload = ip + 1;
|
||||
if (!is_ipv4_fragment(ip)) {
|
||||
payload_length = len - sizeof(*ip);
|
||||
payload_length = len - sizeof(*ip);
|
||||
pseudo_checksum = ipv4_pseudo_header_checksum(ip, payload_length);
|
||||
}
|
||||
ASSERT_TRUE(protocol == IPPROTO_TCP || protocol == IPPROTO_UDP || protocol == IPPROTO_ICMP)
|
||||
<< msg << ": Unsupported IPv4 protocol " << protocol << "\n";
|
||||
<< msg << ": Unsupported IPv4 protocol " << protocol << "\n";
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
struct ip6_hdr *ip6 = (struct ip6_hdr *) packet;
|
||||
struct ip6_hdr *ip6 = (struct ip6_hdr *)packet;
|
||||
ASSERT_GE(len, sizeof(*ip6)) << msg << ": IPv6 packet shorter than IPv6 header\n";
|
||||
EXPECT_EQ(len - sizeof(*ip6), htons(ip6->ip6_plen)) << msg << ": Incorrect IPv6 length\n";
|
||||
|
||||
if (ip6->ip6_nxt == IPPROTO_FRAGMENT) {
|
||||
struct ip6_frag *frag = (struct ip6_frag *) (ip6 + 1);
|
||||
struct ip6_frag *frag = (struct ip6_frag *)(ip6 + 1);
|
||||
ASSERT_GE(len, sizeof(*ip6) + sizeof(*frag))
|
||||
<< msg << ": IPv6 fragment: short fragment header\n";
|
||||
<< msg << ": IPv6 fragment: short fragment header\n";
|
||||
protocol = frag->ip6f_nxt;
|
||||
payload = frag + 1;
|
||||
payload = frag + 1;
|
||||
// Even though the packet has a Fragment header, it might not be a fragment.
|
||||
if (!is_ipv6_fragment(ip6, len)) {
|
||||
payload_length = len - sizeof(*ip6) - sizeof(*frag);
|
||||
}
|
||||
} else {
|
||||
// Since there are no extension headers except Fragment, this must be the payload.
|
||||
protocol = ip6->ip6_nxt;
|
||||
payload = ip6 + 1;
|
||||
protocol = ip6->ip6_nxt;
|
||||
payload = ip6 + 1;
|
||||
payload_length = len - sizeof(*ip6);
|
||||
}
|
||||
ASSERT_TRUE(protocol == IPPROTO_TCP || protocol == IPPROTO_UDP || protocol == IPPROTO_ICMPV6)
|
||||
<< msg << ": Unsupported IPv6 next header " << protocol;
|
||||
<< msg << ": Unsupported IPv6 next header " << protocol;
|
||||
if (payload_length) {
|
||||
pseudo_checksum = ipv6_pseudo_header_checksum(ip6, payload_length, protocol);
|
||||
}
|
||||
|
|
@ -257,7 +259,7 @@ void check_packet(const uint8_t *packet, size_t len, const char *msg) {
|
|||
// If we understand the payload, verify the checksum.
|
||||
if (payload_length) {
|
||||
uint16_t checksum;
|
||||
switch(protocol) {
|
||||
switch (protocol) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMPV6:
|
||||
|
|
@ -274,7 +276,7 @@ void check_packet(const uint8_t *packet, size_t len, const char *msg) {
|
|||
}
|
||||
|
||||
if (protocol == IPPROTO_UDP) {
|
||||
struct udphdr *udp = (struct udphdr *) payload;
|
||||
struct udphdr *udp = (struct udphdr *)payload;
|
||||
EXPECT_NE(0, udp->check) << msg << ": UDP checksum 0 should be 0xffff";
|
||||
// If this is not a fragment, check the UDP length field.
|
||||
if (payload_length) {
|
||||
|
|
@ -285,15 +287,15 @@ void check_packet(const uint8_t *packet, size_t len, const char *msg) {
|
|||
|
||||
void reassemble_packet(const uint8_t **fragments, const size_t lengths[], int numpackets,
|
||||
uint8_t *reassembled, size_t *reassembled_len, const char *msg) {
|
||||
struct iphdr *ip = NULL;
|
||||
struct iphdr *ip = NULL;
|
||||
struct ip6_hdr *ip6 = NULL;
|
||||
size_t total_length, pos = 0;
|
||||
size_t total_length, pos = 0;
|
||||
uint8_t protocol = 0;
|
||||
uint8_t version = ip_version(fragments[0]);
|
||||
uint8_t version = ip_version(fragments[0]);
|
||||
|
||||
for (int i = 0; i < numpackets; i++) {
|
||||
const uint8_t *packet = fragments[i];
|
||||
int len = lengths[i];
|
||||
int len = lengths[i];
|
||||
int headersize, payload_offset;
|
||||
|
||||
ASSERT_EQ(ip_version(packet), version) << msg << ": Inconsistent fragment versions\n";
|
||||
|
|
@ -301,32 +303,32 @@ void reassemble_packet(const uint8_t **fragments, const size_t lengths[], int nu
|
|||
|
||||
switch (version) {
|
||||
case 4: {
|
||||
struct iphdr *ip_orig = (struct iphdr *) packet;
|
||||
headersize = sizeof(*ip_orig);
|
||||
struct iphdr *ip_orig = (struct iphdr *)packet;
|
||||
headersize = sizeof(*ip_orig);
|
||||
ASSERT_TRUE(is_ipv4_fragment(ip_orig))
|
||||
<< msg << ": IPv4 fragment #" << i + 1 << " not a fragment\n";
|
||||
ASSERT_EQ(pos, ipv4_fragment_offset(ip_orig) * 8 + ((i != 0) ? sizeof(*ip): 0))
|
||||
<< msg << ": IPv4 fragment #" << i + 1 << ": inconsistent offset\n";
|
||||
<< msg << ": IPv4 fragment #" << i + 1 << " not a fragment\n";
|
||||
ASSERT_EQ(pos, ipv4_fragment_offset(ip_orig) * 8 + ((i != 0) ? sizeof(*ip) : 0))
|
||||
<< msg << ": IPv4 fragment #" << i + 1 << ": inconsistent offset\n";
|
||||
|
||||
headersize = sizeof(*ip_orig);
|
||||
headersize = sizeof(*ip_orig);
|
||||
payload_offset = headersize;
|
||||
if (pos == 0) {
|
||||
ip = (struct iphdr *) reassembled;
|
||||
ip = (struct iphdr *)reassembled;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
struct ip6_hdr *ip6_orig = (struct ip6_hdr *) packet;
|
||||
struct ip6_frag *frag = (struct ip6_frag *) (ip6_orig + 1);
|
||||
struct ip6_hdr *ip6_orig = (struct ip6_hdr *)packet;
|
||||
struct ip6_frag *frag = (struct ip6_frag *)(ip6_orig + 1);
|
||||
ASSERT_TRUE(is_ipv6_fragment(ip6_orig, len))
|
||||
<< msg << ": IPv6 fragment #" << i + 1 << " not a fragment\n";
|
||||
ASSERT_EQ(pos, ipv6_fragment_offset(frag) * 8 + ((i != 0) ? sizeof(*ip6): 0))
|
||||
<< msg << ": IPv6 fragment #" << i + 1 << ": inconsistent offset\n";
|
||||
<< msg << ": IPv6 fragment #" << i + 1 << " not a fragment\n";
|
||||
ASSERT_EQ(pos, ipv6_fragment_offset(frag) * 8 + ((i != 0) ? sizeof(*ip6) : 0))
|
||||
<< msg << ": IPv6 fragment #" << i + 1 << ": inconsistent offset\n";
|
||||
|
||||
headersize = sizeof(*ip6_orig);
|
||||
headersize = sizeof(*ip6_orig);
|
||||
payload_offset = sizeof(*ip6_orig) + sizeof(*frag);
|
||||
if (pos == 0) {
|
||||
ip6 = (struct ip6_hdr *) reassembled;
|
||||
ip6 = (struct ip6_hdr *)reassembled;
|
||||
protocol = frag->ip6f_nxt;
|
||||
}
|
||||
break;
|
||||
|
|
@ -337,7 +339,7 @@ void reassemble_packet(const uint8_t **fragments, const size_t lengths[], int nu
|
|||
|
||||
// If this is the first fragment, copy the header.
|
||||
if (pos == 0) {
|
||||
ASSERT_LT(headersize, (int) *reassembled_len) << msg << ": Reassembly buffer too small\n";
|
||||
ASSERT_LT(headersize, (int)*reassembled_len) << msg << ": Reassembly buffer too small\n";
|
||||
memcpy(reassembled, packet, headersize);
|
||||
total_length = headersize;
|
||||
pos += headersize;
|
||||
|
|
@ -351,21 +353,20 @@ void reassemble_packet(const uint8_t **fragments, const size_t lengths[], int nu
|
|||
pos += payload_length;
|
||||
}
|
||||
|
||||
|
||||
// Fix up the reassembled headers to reflect fragmentation and length (and IPv4 checksum).
|
||||
ASSERT_EQ(total_length, pos) << msg << ": Reassembled packet length incorrect\n";
|
||||
if (ip) {
|
||||
ip->frag_off &= ~htons(IP_MF);
|
||||
ip->tot_len = htons(total_length);
|
||||
ip->check = 0;
|
||||
ip->check = ip_checksum(ip, sizeof(*ip));
|
||||
ip->check = 0;
|
||||
ip->check = ip_checksum(ip, sizeof(*ip));
|
||||
ASSERT_FALSE(is_ipv4_fragment(ip)) << msg << ": reassembled IPv4 packet is a fragment!\n";
|
||||
}
|
||||
if (ip6) {
|
||||
ip6->ip6_nxt = protocol;
|
||||
ip6->ip6_nxt = protocol;
|
||||
ip6->ip6_plen = htons(total_length - sizeof(*ip6));
|
||||
ASSERT_FALSE(is_ipv6_fragment(ip6, ip6->ip6_plen))
|
||||
<< msg << ": reassembled IPv6 packet is a fragment!\n";
|
||||
<< msg << ": reassembled IPv6 packet is a fragment!\n";
|
||||
}
|
||||
|
||||
*reassembled_len = total_length;
|
||||
|
|
@ -383,8 +384,8 @@ void check_data_matches(const void *expected, const void *actual, size_t len, co
|
|||
snprintf(actual_hexdump + pos, hexdump_len - pos, "\n ");
|
||||
pos += 4;
|
||||
}
|
||||
snprintf(expected_hexdump + pos, hexdump_len - pos, " %02x", ((uint8_t *) expected)[i]);
|
||||
snprintf(actual_hexdump + pos, hexdump_len - pos, " %02x", ((uint8_t *) actual)[i]);
|
||||
snprintf(expected_hexdump + pos, hexdump_len - pos, " %02x", ((uint8_t *)expected)[i]);
|
||||
snprintf(actual_hexdump + pos, hexdump_len - pos, " %02x", ((uint8_t *)actual)[i]);
|
||||
pos += 3;
|
||||
}
|
||||
FAIL() << msg << ": Data doesn't match"
|
||||
|
|
@ -393,27 +394,27 @@ void check_data_matches(const void *expected, const void *actual, size_t len, co
|
|||
}
|
||||
}
|
||||
|
||||
void fix_udp_checksum(uint8_t* packet) {
|
||||
void fix_udp_checksum(uint8_t *packet) {
|
||||
uint32_t pseudo_checksum;
|
||||
uint8_t version = ip_version(packet);
|
||||
struct udphdr *udp;
|
||||
switch (version) {
|
||||
case 4: {
|
||||
struct iphdr *ip = (struct iphdr *) packet;
|
||||
udp = (struct udphdr *) (ip + 1);
|
||||
pseudo_checksum = ipv4_pseudo_header_checksum(ip, ntohs(udp->len));
|
||||
struct iphdr *ip = (struct iphdr *)packet;
|
||||
udp = (struct udphdr *)(ip + 1);
|
||||
pseudo_checksum = ipv4_pseudo_header_checksum(ip, ntohs(udp->len));
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
struct ip6_hdr *ip6 = (struct ip6_hdr *) packet;
|
||||
udp = (struct udphdr *) (ip6 + 1);
|
||||
pseudo_checksum = ipv6_pseudo_header_checksum(ip6, ntohs(udp->len), IPPROTO_UDP);
|
||||
struct ip6_hdr *ip6 = (struct ip6_hdr *)packet;
|
||||
udp = (struct udphdr *)(ip6 + 1);
|
||||
pseudo_checksum = ipv6_pseudo_header_checksum(ip6, ntohs(udp->len), IPPROTO_UDP);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
FAIL() << "unsupported IP version" << version << "\n";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
udp->check = 0;
|
||||
udp->check = ip_checksum_finish(ip_checksum_add(pseudo_checksum, udp, ntohs(udp->len)));
|
||||
|
|
@ -422,9 +423,7 @@ void fix_udp_checksum(uint8_t* packet) {
|
|||
// Testing stub for send_rawv6. The real version uses sendmsg() with a
|
||||
// destination IPv6 address, and attempting to call that on our test socketpair
|
||||
// fd results in EINVAL.
|
||||
extern "C" void send_rawv6(int fd, clat_packet out, int iov_len) {
|
||||
writev(fd, out, iov_len);
|
||||
}
|
||||
extern "C" void send_rawv6(int fd, clat_packet out, int iov_len) { writev(fd, out, iov_len); }
|
||||
|
||||
void do_translate_packet(const uint8_t *original, size_t original_len, uint8_t *out, size_t *outlen,
|
||||
const char *msg) {
|
||||
|
|
@ -443,13 +442,13 @@ void do_translate_packet(const uint8_t *original, size_t original_len, uint8_t *
|
|||
switch (version) {
|
||||
case 4:
|
||||
expected_proto = htons(ETH_P_IPV6);
|
||||
read_fd = fds[1];
|
||||
write_fd = fds[0];
|
||||
read_fd = fds[1];
|
||||
write_fd = fds[0];
|
||||
break;
|
||||
case 6:
|
||||
expected_proto = htons(ETH_P_IP);
|
||||
read_fd = fds[0];
|
||||
write_fd = fds[1];
|
||||
read_fd = fds[0];
|
||||
write_fd = fds[1];
|
||||
break;
|
||||
default:
|
||||
FAIL() << msg << ": Unsupported IP version " << version << "\n";
|
||||
|
|
@ -464,11 +463,12 @@ void do_translate_packet(const uint8_t *original, size_t original_len, uint8_t *
|
|||
struct tun_pi new_tun_header;
|
||||
struct iovec iov[] = {
|
||||
{ &new_tun_header, sizeof(new_tun_header) },
|
||||
{ out, *outlen }
|
||||
{ out, *outlen },
|
||||
};
|
||||
|
||||
int len = readv(read_fd, iov, 2);
|
||||
if (len > (int) sizeof(new_tun_header)) {
|
||||
ASSERT_LT((size_t) len, *outlen) << msg << ": Translated packet buffer too small\n";
|
||||
if (len > (int)sizeof(new_tun_header)) {
|
||||
ASSERT_LT((size_t)len, *outlen) << msg << ": Translated packet buffer too small\n";
|
||||
EXPECT_EQ(expected_proto, new_tun_header.proto) << msg << "Unexpected tun proto\n";
|
||||
*outlen = len - sizeof(new_tun_header);
|
||||
check_packet(out, *outlen, msg);
|
||||
|
|
@ -483,8 +483,8 @@ void do_translate_packet(const uint8_t *original, size_t original_len, uint8_t *
|
|||
}
|
||||
}
|
||||
|
||||
void check_translated_packet(const uint8_t *original, size_t original_len,
|
||||
const uint8_t *expected, size_t expected_len, const char *msg) {
|
||||
void check_translated_packet(const uint8_t *original, size_t original_len, const uint8_t *expected,
|
||||
size_t expected_len, const char *msg) {
|
||||
uint8_t translated[MAXMTU];
|
||||
size_t translated_len = sizeof(translated);
|
||||
do_translate_packet(original, original_len, translated, &translated_len, msg);
|
||||
|
|
@ -499,8 +499,8 @@ void check_fragment_translation(const uint8_t *original[], const size_t original
|
|||
// Check that each of the fragments translates as expected.
|
||||
char frag_msg[512];
|
||||
snprintf(frag_msg, sizeof(frag_msg), "%s: fragment #%d", msg, i + 1);
|
||||
check_translated_packet(original[i], original_lengths[i],
|
||||
expected[i], expected_lengths[i], frag_msg);
|
||||
check_translated_packet(original[i], original_lengths[i], expected[i], expected_lengths[i],
|
||||
frag_msg);
|
||||
}
|
||||
|
||||
// Sanity check that reassembling the original and translated fragments produces valid packets.
|
||||
|
|
@ -524,17 +524,17 @@ int get_transport_checksum(const uint8_t *packet) {
|
|||
int version = ip_version(packet);
|
||||
switch (version) {
|
||||
case 4:
|
||||
ip = (struct iphdr *) packet;
|
||||
ip = (struct iphdr *)packet;
|
||||
if (is_ipv4_fragment(ip)) {
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
protocol = ip->protocol;
|
||||
payload = ip + 1;
|
||||
payload = ip + 1;
|
||||
break;
|
||||
case 6:
|
||||
ip6 = (struct ip6_hdr *) packet;
|
||||
ip6 = (struct ip6_hdr *)packet;
|
||||
protocol = ip6->ip6_nxt;
|
||||
payload = ip6 + 1;
|
||||
payload = ip6 + 1;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
|
|
@ -542,10 +542,10 @@ int get_transport_checksum(const uint8_t *packet) {
|
|||
|
||||
switch (protocol) {
|
||||
case IPPROTO_UDP:
|
||||
return ((struct udphdr *) payload)->check;
|
||||
return ((struct udphdr *)payload)->check;
|
||||
|
||||
case IPPROTO_TCP:
|
||||
return ((struct tcphdr *) payload)->check;
|
||||
return ((struct tcphdr *)payload)->check;
|
||||
|
||||
case IPPROTO_FRAGMENT:
|
||||
default:
|
||||
|
|
@ -561,7 +561,7 @@ class ClatdTest : public ::testing::Test {
|
|||
inet_pton(AF_INET, kIPv4LocalAddr, &Global_Clatd_Config.ipv4_local_subnet);
|
||||
inet_pton(AF_INET6, kIPv6PlatSubnet, &Global_Clatd_Config.plat_subnet);
|
||||
inet_pton(AF_INET6, kIPv6LocalAddr, &Global_Clatd_Config.ipv6_local_subnet);
|
||||
Global_Clatd_Config.ipv6_host_id = in6addr_any;
|
||||
Global_Clatd_Config.ipv6_host_id = in6addr_any;
|
||||
Global_Clatd_Config.use_dynamic_iid = 1;
|
||||
}
|
||||
};
|
||||
|
|
@ -597,7 +597,7 @@ TEST_F(ClatdTest, TestIPv6PrefixEqual) {
|
|||
int count_onebits(const void *data, size_t size) {
|
||||
int onebits = 0;
|
||||
for (size_t pos = 0; pos < size; pos++) {
|
||||
uint8_t *byte = ((uint8_t*) data) + pos;
|
||||
uint8_t *byte = ((uint8_t *)data) + pos;
|
||||
for (int shift = 0; shift < 8; shift++) {
|
||||
onebits += (*byte >> shift) & 1;
|
||||
}
|
||||
|
|
@ -611,7 +611,7 @@ TEST_F(ClatdTest, TestCountOnebits) {
|
|||
ASSERT_EQ(1, count_onebits(&i, sizeof(i)));
|
||||
i <<= 61;
|
||||
ASSERT_EQ(1, count_onebits(&i, sizeof(i)));
|
||||
i |= ((uint64_t) 1 << 33);
|
||||
i |= ((uint64_t)1 << 33);
|
||||
ASSERT_EQ(2, count_onebits(&i, sizeof(i)));
|
||||
i = 0xf1000202020000f0;
|
||||
ASSERT_EQ(5 + 1 + 1 + 1 + 4, count_onebits(&i, sizeof(i)));
|
||||
|
|
@ -637,10 +637,10 @@ TEST_F(ClatdTest, TestGenIIDRandom) {
|
|||
Global_Clatd_Config.ipv6_host_id = in6addr_any;
|
||||
|
||||
// Generate a boatload of random IIDs.
|
||||
int onebits = 0;
|
||||
int onebits = 0;
|
||||
uint64_t prev_iid = 0;
|
||||
for (int i = 0; i < 100000; i++) {
|
||||
struct in6_addr myaddr = interface_ipv6;
|
||||
struct in6_addr myaddr = interface_ipv6;
|
||||
|
||||
config_generate_local_ipv6_subnet(&myaddr);
|
||||
|
||||
|
|
@ -648,7 +648,7 @@ TEST_F(ClatdTest, TestGenIIDRandom) {
|
|||
EXPECT_TRUE(ipv6_prefix_equal(&interface_ipv6, &myaddr));
|
||||
|
||||
// Check that consecutive IIDs are not the same.
|
||||
uint64_t iid = * (uint64_t*) (&myaddr.s6_addr[8]);
|
||||
uint64_t iid = *(uint64_t *)(&myaddr.s6_addr[8]);
|
||||
ASSERT_TRUE(iid != prev_iid)
|
||||
<< "Two consecutive random IIDs are the same: "
|
||||
<< std::showbase << std::hex
|
||||
|
|
@ -657,7 +657,7 @@ TEST_F(ClatdTest, TestGenIIDRandom) {
|
|||
|
||||
// Check that the IID is checksum-neutral with the NAT64 prefix and the
|
||||
// local prefix.
|
||||
struct in_addr *ipv4addr = &Global_Clatd_Config.ipv4_local_subnet;
|
||||
struct in_addr *ipv4addr = &Global_Clatd_Config.ipv4_local_subnet;
|
||||
struct in6_addr *plat_subnet = &Global_Clatd_Config.plat_subnet;
|
||||
|
||||
uint16_t c1 = ip_checksum_finish(ip_checksum_add(0, ipv4addr, sizeof(*ipv4addr)));
|
||||
|
|
@ -732,7 +732,7 @@ TEST_F(ClatdTest, SelectIPv4Address) {
|
|||
// Now try using the real function which sees if IP addresses are free using bind().
|
||||
// Assume that the machine running the test has the address 127.0.0.1, but not 8.8.8.8.
|
||||
config_is_ipv4_address_free = orig_config_is_ipv4_address_free;
|
||||
addr.s_addr = inet_addr("8.8.8.8");
|
||||
addr.s_addr = inet_addr("8.8.8.8");
|
||||
EXPECT_EQ(inet_addr("8.8.8.8"), config_select_ipv4_address(&addr, 29));
|
||||
|
||||
addr.s_addr = inet_addr("127.0.0.1");
|
||||
|
|
@ -753,13 +753,13 @@ TEST_F(ClatdTest, DataSanitycheck) {
|
|||
// Sanity checks check_packet.
|
||||
struct udphdr *udp;
|
||||
uint8_t v4_udp_packet[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
|
||||
udp = (struct udphdr *) (v4_udp_packet + sizeof(struct iphdr));
|
||||
udp = (struct udphdr *)(v4_udp_packet + sizeof(struct iphdr));
|
||||
fix_udp_checksum(v4_udp_packet);
|
||||
ASSERT_EQ(kUdpV4Checksum, udp->check) << "UDP/IPv4 packet checksum sanity check\n";
|
||||
check_packet(v4_udp_packet, sizeof(v4_udp_packet), "UDP/IPv4 packet sanity check");
|
||||
|
||||
uint8_t v6_udp_packet[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
|
||||
udp = (struct udphdr *) (v6_udp_packet + sizeof(struct ip6_hdr));
|
||||
udp = (struct udphdr *)(v6_udp_packet + sizeof(struct ip6_hdr));
|
||||
fix_udp_checksum(v6_udp_packet);
|
||||
ASSERT_EQ(kUdpV6Checksum, udp->check) << "UDP/IPv6 packet checksum sanity check\n";
|
||||
check_packet(v6_udp_packet, sizeof(v6_udp_packet), "UDP/IPv6 packet sanity check");
|
||||
|
|
@ -773,53 +773,53 @@ TEST_F(ClatdTest, DataSanitycheck) {
|
|||
// Sanity checks reassemble_packet.
|
||||
uint8_t reassembled[MAXMTU];
|
||||
size_t total_length = sizeof(reassembled);
|
||||
reassemble_packet(kIPv4Fragments, kIPv4FragLengths, ARRAYSIZE(kIPv4Fragments),
|
||||
reassembled, &total_length, "Reassembly sanity check");
|
||||
reassemble_packet(kIPv4Fragments, kIPv4FragLengths, ARRAYSIZE(kIPv4Fragments), reassembled,
|
||||
&total_length, "Reassembly sanity check");
|
||||
check_packet(reassembled, total_length, "IPv4 Reassembled packet is valid");
|
||||
ASSERT_EQ(sizeof(kReassembledIPv4), total_length) << "IPv4 reassembly sanity check: length\n";
|
||||
ASSERT_TRUE(!is_ipv4_fragment((struct iphdr *) reassembled))
|
||||
<< "Sanity check: reassembled packet is a fragment!\n";
|
||||
ASSERT_TRUE(!is_ipv4_fragment((struct iphdr *)reassembled))
|
||||
<< "Sanity check: reassembled packet is a fragment!\n";
|
||||
check_data_matches(kReassembledIPv4, reassembled, total_length, "IPv4 reassembly sanity check");
|
||||
|
||||
total_length = sizeof(reassembled);
|
||||
reassemble_packet(kIPv6Fragments, kIPv6FragLengths, ARRAYSIZE(kIPv6Fragments),
|
||||
reassembled, &total_length, "IPv6 reassembly sanity check");
|
||||
ASSERT_TRUE(!is_ipv6_fragment((struct ip6_hdr *) reassembled, total_length))
|
||||
<< "Sanity check: reassembled packet is a fragment!\n";
|
||||
reassemble_packet(kIPv6Fragments, kIPv6FragLengths, ARRAYSIZE(kIPv6Fragments), reassembled,
|
||||
&total_length, "IPv6 reassembly sanity check");
|
||||
ASSERT_TRUE(!is_ipv6_fragment((struct ip6_hdr *)reassembled, total_length))
|
||||
<< "Sanity check: reassembled packet is a fragment!\n";
|
||||
check_packet(reassembled, total_length, "IPv6 Reassembled packet is valid");
|
||||
}
|
||||
|
||||
TEST_F(ClatdTest, PseudoChecksum) {
|
||||
uint32_t pseudo_checksum;
|
||||
|
||||
uint8_t v4_header[] = { IPV4_UDP_HEADER };
|
||||
uint8_t v4_header[] = { IPV4_UDP_HEADER };
|
||||
uint8_t v4_pseudo_header[] = { IPV4_PSEUDOHEADER(v4_header, UDP_LEN) };
|
||||
pseudo_checksum = ipv4_pseudo_header_checksum((struct iphdr *) v4_header, UDP_LEN);
|
||||
pseudo_checksum = ipv4_pseudo_header_checksum((struct iphdr *)v4_header, UDP_LEN);
|
||||
EXPECT_EQ(ip_checksum_finish(pseudo_checksum),
|
||||
ip_checksum(v4_pseudo_header, sizeof(v4_pseudo_header)))
|
||||
<< "ipv4_pseudo_header_checksum incorrect\n";
|
||||
<< "ipv4_pseudo_header_checksum incorrect\n";
|
||||
|
||||
uint8_t v6_header[] = { IPV6_UDP_HEADER };
|
||||
uint8_t v6_header[] = { IPV6_UDP_HEADER };
|
||||
uint8_t v6_pseudo_header[] = { IPV6_PSEUDOHEADER(v6_header, IPPROTO_UDP, UDP_LEN) };
|
||||
pseudo_checksum = ipv6_pseudo_header_checksum((struct ip6_hdr *) v6_header, UDP_LEN, IPPROTO_UDP);
|
||||
pseudo_checksum = ipv6_pseudo_header_checksum((struct ip6_hdr *)v6_header, UDP_LEN, IPPROTO_UDP);
|
||||
EXPECT_EQ(ip_checksum_finish(pseudo_checksum),
|
||||
ip_checksum(v6_pseudo_header, sizeof(v6_pseudo_header)))
|
||||
<< "ipv6_pseudo_header_checksum incorrect\n";
|
||||
<< "ipv6_pseudo_header_checksum incorrect\n";
|
||||
}
|
||||
|
||||
TEST_F(ClatdTest, TransportChecksum) {
|
||||
uint8_t udphdr[] = { UDP_HEADER };
|
||||
uint8_t udphdr[] = { UDP_HEADER };
|
||||
uint8_t payload[] = { PAYLOAD };
|
||||
EXPECT_EQ(kUdpPartialChecksum, ip_checksum_add(0, udphdr, sizeof(udphdr)))
|
||||
<< "UDP partial checksum\n";
|
||||
<< "UDP partial checksum\n";
|
||||
EXPECT_EQ(kPayloadPartialChecksum, ip_checksum_add(0, payload, sizeof(payload)))
|
||||
<< "Payload partial checksum\n";
|
||||
<< "Payload partial checksum\n";
|
||||
|
||||
uint8_t ip[] = { IPV4_UDP_HEADER };
|
||||
uint8_t ip6[] = { IPV6_UDP_HEADER };
|
||||
uint32_t ipv4_pseudo_sum = ipv4_pseudo_header_checksum((struct iphdr *) ip, UDP_LEN);
|
||||
uint32_t ipv6_pseudo_sum = ipv6_pseudo_header_checksum((struct ip6_hdr *) ip6, UDP_LEN,
|
||||
IPPROTO_UDP);
|
||||
uint8_t ip[] = { IPV4_UDP_HEADER };
|
||||
uint8_t ip6[] = { IPV6_UDP_HEADER };
|
||||
uint32_t ipv4_pseudo_sum = ipv4_pseudo_header_checksum((struct iphdr *)ip, UDP_LEN);
|
||||
uint32_t ipv6_pseudo_sum =
|
||||
ipv6_pseudo_header_checksum((struct ip6_hdr *)ip6, UDP_LEN, IPPROTO_UDP);
|
||||
|
||||
EXPECT_EQ(0x3ad0U, ipv4_pseudo_sum) << "IPv4 pseudo-checksum sanity check\n";
|
||||
EXPECT_EQ(0x2644bU, ipv6_pseudo_sum) << "IPv6 pseudo-checksum sanity check\n";
|
||||
|
|
@ -886,12 +886,10 @@ TEST_F(ClatdTest, Translate) {
|
|||
}
|
||||
|
||||
TEST_F(ClatdTest, Fragmentation) {
|
||||
check_fragment_translation(kIPv4Fragments, kIPv4FragLengths,
|
||||
kIPv6Fragments, kIPv6FragLengths,
|
||||
check_fragment_translation(kIPv4Fragments, kIPv4FragLengths, kIPv6Fragments, kIPv6FragLengths,
|
||||
ARRAYSIZE(kIPv4Fragments), "IPv4->IPv6 fragment translation");
|
||||
|
||||
check_fragment_translation(kIPv6Fragments, kIPv6FragLengths,
|
||||
kIPv4Fragments, kIPv4FragLengths,
|
||||
check_fragment_translation(kIPv6Fragments, kIPv6FragLengths, kIPv4Fragments, kIPv4FragLengths,
|
||||
ARRAYSIZE(kIPv6Fragments), "IPv6->IPv4 fragment translation");
|
||||
}
|
||||
|
||||
|
|
@ -902,12 +900,12 @@ void check_translate_checksum_neutral(const uint8_t *original, size_t original_l
|
|||
do_translate_packet(original, original_len, translated, &translated_len, msg);
|
||||
EXPECT_EQ(expected_len, translated_len) << msg << ": Translated packet length incorrect\n";
|
||||
// do_translate_packet already checks packets for validity and verifies the checksum.
|
||||
int original_check = get_transport_checksum(original);
|
||||
int original_check = get_transport_checksum(original);
|
||||
int translated_check = get_transport_checksum(translated);
|
||||
ASSERT_NE(-1, original_check);
|
||||
ASSERT_NE(-1, translated_check);
|
||||
ASSERT_EQ(original_check, translated_check)
|
||||
<< "Not checksum neutral: original and translated checksums differ\n";
|
||||
<< "Not checksum neutral: original and translated checksums differ\n";
|
||||
}
|
||||
|
||||
TEST_F(ClatdTest, TranslateChecksumNeutral) {
|
||||
|
|
@ -916,8 +914,8 @@ TEST_F(ClatdTest, TranslateChecksumNeutral) {
|
|||
ASSERT_TRUE(inet_pton(AF_INET6, "2001:db8:1:2:f076:ae99:124e:aa54",
|
||||
&Global_Clatd_Config.ipv6_local_subnet));
|
||||
config_generate_local_ipv6_subnet(&Global_Clatd_Config.ipv6_local_subnet);
|
||||
ASSERT_NE((uint32_t) 0x00000464, Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
|
||||
ASSERT_NE((uint32_t) 0, Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
|
||||
ASSERT_NE((uint32_t)0x00000464, Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
|
||||
ASSERT_NE((uint32_t)0, Global_Clatd_Config.ipv6_local_subnet.s6_addr32[3]);
|
||||
|
||||
// Check that translating UDP packets is checksum-neutral. First, IPv4.
|
||||
uint8_t udp_ipv4[] = { IPV4_UDP_HEADER UDP_HEADER PAYLOAD };
|
||||
|
|
@ -928,7 +926,7 @@ TEST_F(ClatdTest, TranslateChecksumNeutral) {
|
|||
// Now try IPv6.
|
||||
uint8_t udp_ipv6[] = { IPV6_UDP_HEADER UDP_HEADER PAYLOAD };
|
||||
// The test packet uses the static IID, not the random IID. Fix up the source address.
|
||||
struct ip6_hdr *ip6 = (struct ip6_hdr *) udp_ipv6;
|
||||
struct ip6_hdr *ip6 = (struct ip6_hdr *)udp_ipv6;
|
||||
memcpy(&ip6->ip6_src, &Global_Clatd_Config.ipv6_local_subnet, sizeof(ip6->ip6_src));
|
||||
fix_udp_checksum(udp_ipv6);
|
||||
check_translate_checksum_neutral(udp_ipv4, sizeof(udp_ipv4), sizeof(udp_ipv4) + 20,
|
||||
|
|
|
|||
267
config.c
267
config.c
|
|
@ -16,75 +16,80 @@
|
|||
* config.c - configuration settings
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cutils/config_utils.h>
|
||||
#include <netutils/ifc.h>
|
||||
|
||||
#include "checksum.h"
|
||||
#include "clatd.h"
|
||||
#include "config.h"
|
||||
#include "dns64.h"
|
||||
#include "logging.h"
|
||||
#include "getaddr.h"
|
||||
#include "clatd.h"
|
||||
#include "checksum.h"
|
||||
#include "logging.h"
|
||||
|
||||
struct clat_config Global_Clatd_Config;
|
||||
|
||||
/* function: config_item_str
|
||||
* locates the config item and returns the pointer to a string, or NULL on failure. Caller frees pointer
|
||||
* root - parsed configuration
|
||||
* item_name - name of config item to locate
|
||||
* defaultvar - value to use if config item isn't present
|
||||
* locates the config item and returns the pointer to a string, or NULL on failure. Caller frees
|
||||
* pointer
|
||||
* root - parsed configuration
|
||||
* item_name - name of config item to locate
|
||||
* defaultvar - value to use if config item isn't present
|
||||
*/
|
||||
char *config_item_str(cnode *root, const char *item_name, const char *defaultvar) {
|
||||
const char *tmp;
|
||||
|
||||
if(!(tmp = config_str(root, item_name, defaultvar))) {
|
||||
logmsg(ANDROID_LOG_FATAL,"%s config item needed",item_name);
|
||||
if (!(tmp = config_str(root, item_name, defaultvar))) {
|
||||
logmsg(ANDROID_LOG_FATAL, "%s config item needed", item_name);
|
||||
return NULL;
|
||||
}
|
||||
return strdup(tmp);
|
||||
}
|
||||
|
||||
/* function: config_item_int16_t
|
||||
* locates the config item, parses the integer, and returns the pointer ret_val_ptr, or NULL on failure
|
||||
* root - parsed configuration
|
||||
* item_name - name of config item to locate
|
||||
* defaultvar - value to use if config item isn't present
|
||||
* ret_val_ptr - pointer for return value storage
|
||||
* locates the config item, parses the integer, and returns the pointer ret_val_ptr, or NULL on
|
||||
* failure
|
||||
* root - parsed configuration
|
||||
* item_name - name of config item to locate
|
||||
* defaultvar - value to use if config item isn't present
|
||||
* ret_val_ptr - pointer for return value storage
|
||||
*/
|
||||
int16_t *config_item_int16_t(cnode *root, const char *item_name, const char *defaultvar, int16_t *ret_val_ptr) {
|
||||
int16_t *config_item_int16_t(cnode *root, const char *item_name, const char *defaultvar,
|
||||
int16_t *ret_val_ptr) {
|
||||
const char *tmp;
|
||||
char *endptr;
|
||||
long int conf_int;
|
||||
|
||||
if(!(tmp = config_str(root, item_name, defaultvar))) {
|
||||
logmsg(ANDROID_LOG_FATAL,"%s config item needed",item_name);
|
||||
if (!(tmp = config_str(root, item_name, defaultvar))) {
|
||||
logmsg(ANDROID_LOG_FATAL, "%s config item needed", item_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
conf_int = strtol(tmp,&endptr,10);
|
||||
if(errno > 0) {
|
||||
logmsg(ANDROID_LOG_FATAL,"%s config item is not numeric: %s (error=%s)",item_name,tmp,strerror(errno));
|
||||
errno = 0;
|
||||
conf_int = strtol(tmp, &endptr, 10);
|
||||
if (errno > 0) {
|
||||
logmsg(ANDROID_LOG_FATAL, "%s config item is not numeric: %s (error=%s)", item_name, tmp,
|
||||
strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
if(endptr == tmp || *tmp == '\0') {
|
||||
logmsg(ANDROID_LOG_FATAL,"%s config item is not numeric: %s",item_name,tmp);
|
||||
if (endptr == tmp || *tmp == '\0') {
|
||||
logmsg(ANDROID_LOG_FATAL, "%s config item is not numeric: %s", item_name, tmp);
|
||||
return NULL;
|
||||
}
|
||||
if(*endptr != '\0') {
|
||||
logmsg(ANDROID_LOG_FATAL,"%s config item contains non-numeric characters: %s",item_name,endptr);
|
||||
if (*endptr != '\0') {
|
||||
logmsg(ANDROID_LOG_FATAL, "%s config item contains non-numeric characters: %s", item_name,
|
||||
endptr);
|
||||
return NULL;
|
||||
}
|
||||
if(conf_int > INT16_MAX || conf_int < INT16_MIN) {
|
||||
logmsg(ANDROID_LOG_FATAL,"%s config item is too big/small: %d",item_name,conf_int);
|
||||
if (conf_int > INT16_MAX || conf_int < INT16_MIN) {
|
||||
logmsg(ANDROID_LOG_FATAL, "%s config item is too big/small: %d", item_name, conf_int);
|
||||
return NULL;
|
||||
}
|
||||
*ret_val_ptr = conf_int;
|
||||
|
|
@ -92,24 +97,26 @@ int16_t *config_item_int16_t(cnode *root, const char *item_name, const char *def
|
|||
}
|
||||
|
||||
/* function: config_item_ip
|
||||
* locates the config item, parses the ipv4 address, and returns the pointer ret_val_ptr, or NULL on failure
|
||||
* root - parsed configuration
|
||||
* item_name - name of config item to locate
|
||||
* defaultvar - value to use if config item isn't present
|
||||
* ret_val_ptr - pointer for return value storage
|
||||
* locates the config item, parses the ipv4 address, and returns the pointer ret_val_ptr, or NULL on
|
||||
* failure
|
||||
* root - parsed configuration
|
||||
* item_name - name of config item to locate
|
||||
* defaultvar - value to use if config item isn't present
|
||||
* ret_val_ptr - pointer for return value storage
|
||||
*/
|
||||
struct in_addr *config_item_ip(cnode *root, const char *item_name, const char *defaultvar, struct in_addr *ret_val_ptr) {
|
||||
struct in_addr *config_item_ip(cnode *root, const char *item_name, const char *defaultvar,
|
||||
struct in_addr *ret_val_ptr) {
|
||||
const char *tmp;
|
||||
int status;
|
||||
|
||||
if(!(tmp = config_str(root, item_name, defaultvar))) {
|
||||
logmsg(ANDROID_LOG_FATAL,"%s config item needed",item_name);
|
||||
if (!(tmp = config_str(root, item_name, defaultvar))) {
|
||||
logmsg(ANDROID_LOG_FATAL, "%s config item needed", item_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = inet_pton(AF_INET, tmp, ret_val_ptr);
|
||||
if(status <= 0) {
|
||||
logmsg(ANDROID_LOG_FATAL,"invalid IPv4 address specified for %s: %s", item_name, tmp);
|
||||
if (status <= 0) {
|
||||
logmsg(ANDROID_LOG_FATAL, "invalid IPv4 address specified for %s: %s", item_name, tmp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -117,24 +124,26 @@ struct in_addr *config_item_ip(cnode *root, const char *item_name, const char *d
|
|||
}
|
||||
|
||||
/* function: config_item_ip6
|
||||
* locates the config item, parses the ipv6 address, and returns the pointer ret_val_ptr, or NULL on failure
|
||||
* root - parsed configuration
|
||||
* item_name - name of config item to locate
|
||||
* defaultvar - value to use if config item isn't present
|
||||
* ret_val_ptr - pointer for return value storage
|
||||
* locates the config item, parses the ipv6 address, and returns the pointer ret_val_ptr, or NULL on
|
||||
* failure
|
||||
* root - parsed configuration
|
||||
* item_name - name of config item to locate
|
||||
* defaultvar - value to use if config item isn't present
|
||||
* ret_val_ptr - pointer for return value storage
|
||||
*/
|
||||
struct in6_addr *config_item_ip6(cnode *root, const char *item_name, const char *defaultvar, struct in6_addr *ret_val_ptr) {
|
||||
struct in6_addr *config_item_ip6(cnode *root, const char *item_name, const char *defaultvar,
|
||||
struct in6_addr *ret_val_ptr) {
|
||||
const char *tmp;
|
||||
int status;
|
||||
|
||||
if(!(tmp = config_str(root, item_name, defaultvar))) {
|
||||
logmsg(ANDROID_LOG_FATAL,"%s config item needed",item_name);
|
||||
if (!(tmp = config_str(root, item_name, defaultvar))) {
|
||||
logmsg(ANDROID_LOG_FATAL, "%s config item needed", item_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = inet_pton(AF_INET6, tmp, ret_val_ptr);
|
||||
if(status <= 0) {
|
||||
logmsg(ANDROID_LOG_FATAL,"invalid IPv6 address specified for %s: %s", item_name, tmp);
|
||||
if (status <= 0) {
|
||||
logmsg(ANDROID_LOG_FATAL, "invalid IPv6 address specified for %s: %s", item_name, tmp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -145,7 +154,7 @@ struct in6_addr *config_item_ip6(cnode *root, const char *item_name, const char
|
|||
* frees the memory used by the global config variable
|
||||
*/
|
||||
void free_config() {
|
||||
if(Global_Clatd_Config.plat_from_dns64_hostname) {
|
||||
if (Global_Clatd_Config.plat_from_dns64_hostname) {
|
||||
free(Global_Clatd_Config.plat_from_dns64_hostname);
|
||||
Global_Clatd_Config.plat_from_dns64_hostname = NULL;
|
||||
}
|
||||
|
|
@ -153,17 +162,16 @@ void free_config() {
|
|||
|
||||
/* function: ipv6_prefix_equal
|
||||
* compares the prefixes two ipv6 addresses. assumes the prefix lengths are both /64.
|
||||
* a1 - first address
|
||||
* a2 - second address
|
||||
* returns: 0 if the subnets are different, 1 if they are the same.
|
||||
* a1 - first address
|
||||
* a2 - second address
|
||||
* returns: 0 if the subnets are different, 1 if they are the same.
|
||||
*/
|
||||
int ipv6_prefix_equal(struct in6_addr *a1, struct in6_addr *a2) {
|
||||
return !memcmp(a1, a2, 8);
|
||||
}
|
||||
int ipv6_prefix_equal(struct in6_addr *a1, struct in6_addr *a2) { return !memcmp(a1, a2, 8); }
|
||||
|
||||
/* function: dns64_detection
|
||||
* does dns lookups to set the plat subnet or exits on failure, waits forever for a dns response with a query backoff timer
|
||||
* net_id - (optional) netId to use, NETID_UNSET indicates use of default network
|
||||
* does dns lookups to set the plat subnet or exits on failure, waits forever for a dns response
|
||||
* with a query backoff timer
|
||||
* net_id - (optional) netId to use, NETID_UNSET indicates use of default network
|
||||
*/
|
||||
void dns64_detection(unsigned net_id) {
|
||||
int backoff_sleep, status;
|
||||
|
|
@ -171,16 +179,16 @@ void dns64_detection(unsigned net_id) {
|
|||
|
||||
backoff_sleep = 1;
|
||||
|
||||
while(1) {
|
||||
status = plat_prefix(Global_Clatd_Config.plat_from_dns64_hostname,net_id,&tmp_ptr);
|
||||
if(status > 0) {
|
||||
while (1) {
|
||||
status = plat_prefix(Global_Clatd_Config.plat_from_dns64_hostname, net_id, &tmp_ptr);
|
||||
if (status > 0) {
|
||||
memcpy(&Global_Clatd_Config.plat_subnet, &tmp_ptr, sizeof(struct in6_addr));
|
||||
return;
|
||||
}
|
||||
logmsg(ANDROID_LOG_WARN, "dns64_detection -- error, sleeping for %d seconds", backoff_sleep);
|
||||
sleep(backoff_sleep);
|
||||
backoff_sleep *= 2;
|
||||
if(backoff_sleep >= 1800) {
|
||||
if (backoff_sleep >= 1800) {
|
||||
// Scale down to one DNS query per half hour. Unnecessary DNS queries waste power, and the
|
||||
// benefit is minimal (basically, only limited to the case where a network goes from IPv6-only
|
||||
// to IPv6 with NAT64).
|
||||
|
|
@ -191,9 +199,9 @@ void dns64_detection(unsigned net_id) {
|
|||
|
||||
/* function: gen_random_iid
|
||||
* picks a random interface ID that is checksum neutral with the IPv4 address and the NAT64 prefix
|
||||
* myaddr - IPv6 address to write to
|
||||
* ipv4_local_subnet - clat IPv4 address
|
||||
* plat_subnet - NAT64 prefix
|
||||
* myaddr - IPv6 address to write to
|
||||
* ipv4_local_subnet - clat IPv4 address
|
||||
* plat_subnet - NAT64 prefix
|
||||
*/
|
||||
void gen_random_iid(struct in6_addr *myaddr, struct in_addr *ipv4_local_subnet,
|
||||
struct in6_addr *plat_subnet) {
|
||||
|
|
@ -212,7 +220,7 @@ void gen_random_iid(struct in6_addr *myaddr, struct in_addr *ipv4_local_subnet,
|
|||
uint32_t c2 = ip_checksum_add(0, plat_subnet, sizeof(*plat_subnet)) +
|
||||
ip_checksum_add(0, myaddr, sizeof(*myaddr));
|
||||
|
||||
uint16_t delta = ip_checksum_adjust(middlebytes, c1, c2);
|
||||
uint16_t delta = ip_checksum_adjust(middlebytes, c1, c2);
|
||||
myaddr->s6_addr[11] = delta >> 8;
|
||||
myaddr->s6_addr[12] = delta & 0xff;
|
||||
}
|
||||
|
|
@ -227,10 +235,9 @@ int connect_is_ipv4_address_free(in_addr_t addr) {
|
|||
// Attempt to connect to the address. If the connection succeeds and getsockname returns the same
|
||||
// the address then the address is already assigned to the system and we can't use it.
|
||||
struct sockaddr_in sin = { .sin_family = AF_INET, .sin_addr = { addr }, .sin_port = 53 };
|
||||
socklen_t len = sizeof(sin);
|
||||
int inuse = connect(s, (struct sockaddr *) &sin, sizeof(sin)) == 0 &&
|
||||
getsockname(s, (struct sockaddr *) &sin, &len) == 0 &&
|
||||
(size_t) len >= sizeof(sin) &&
|
||||
socklen_t len = sizeof(sin);
|
||||
int inuse = connect(s, (struct sockaddr *)&sin, sizeof(sin)) == 0 &&
|
||||
getsockname(s, (struct sockaddr *)&sin, &len) == 0 && (size_t)len >= sizeof(sin) &&
|
||||
sin.sin_addr.s_addr == addr;
|
||||
|
||||
close(s);
|
||||
|
|
@ -241,127 +248,123 @@ addr_free_func config_is_ipv4_address_free = connect_is_ipv4_address_free;
|
|||
|
||||
/* function: config_select_ipv4_address
|
||||
* picks a free IPv4 address, starting from ip and trying all addresses in the prefix in order
|
||||
* ip - the IP address from the configuration file
|
||||
* prefixlen - the length of the prefix from which addresses may be selected.
|
||||
* returns: the IPv4 address, or INADDR_NONE if no addresses were available
|
||||
* ip - the IP address from the configuration file
|
||||
* prefixlen - the length of the prefix from which addresses may be selected.
|
||||
* returns: the IPv4 address, or INADDR_NONE if no addresses were available
|
||||
*/
|
||||
in_addr_t config_select_ipv4_address(const struct in_addr *ip, int16_t prefixlen) {
|
||||
in_addr_t chosen = INADDR_NONE;
|
||||
|
||||
// Don't accept prefixes that are too large because we scan addresses one by one.
|
||||
if (prefixlen < 16 || prefixlen > 32) {
|
||||
return chosen;
|
||||
return chosen;
|
||||
}
|
||||
|
||||
// All these are in host byte order.
|
||||
in_addr_t mask = 0xffffffff >> (32 - prefixlen) << (32 - prefixlen);
|
||||
in_addr_t ipv4 = ntohl(ip->s_addr);
|
||||
in_addr_t mask = 0xffffffff >> (32 - prefixlen) << (32 - prefixlen);
|
||||
in_addr_t ipv4 = ntohl(ip->s_addr);
|
||||
in_addr_t first_ipv4 = ipv4;
|
||||
in_addr_t prefix = ipv4 & mask;
|
||||
in_addr_t prefix = ipv4 & mask;
|
||||
|
||||
// Pick the first IPv4 address in the pool, wrapping around if necessary.
|
||||
// So, for example, 192.0.0.4 -> 192.0.0.5 -> 192.0.0.6 -> 192.0.0.7 -> 192.0.0.0.
|
||||
do {
|
||||
if (config_is_ipv4_address_free(htonl(ipv4))) {
|
||||
chosen = htonl(ipv4);
|
||||
break;
|
||||
}
|
||||
ipv4 = prefix | ((ipv4 + 1) & ~mask);
|
||||
if (config_is_ipv4_address_free(htonl(ipv4))) {
|
||||
chosen = htonl(ipv4);
|
||||
break;
|
||||
}
|
||||
ipv4 = prefix | ((ipv4 + 1) & ~mask);
|
||||
} while (ipv4 != first_ipv4);
|
||||
|
||||
return chosen;
|
||||
}
|
||||
|
||||
/* function: config_generate_local_ipv6_subnet
|
||||
* generates the local ipv6 subnet when given the interface ip
|
||||
* requires config.ipv6_host_id
|
||||
* interface_ip - in: interface ip, out: local ipv6 host address
|
||||
* generates the local ipv6 subnet when given the interface ip requires config.ipv6_host_id
|
||||
* interface_ip - in: interface ip, out: local ipv6 host address
|
||||
*/
|
||||
void config_generate_local_ipv6_subnet(struct in6_addr *interface_ip) {
|
||||
int i;
|
||||
|
||||
if (Global_Clatd_Config.use_dynamic_iid) {
|
||||
/* Generate a random interface ID. */
|
||||
gen_random_iid(interface_ip,
|
||||
&Global_Clatd_Config.ipv4_local_subnet,
|
||||
gen_random_iid(interface_ip, &Global_Clatd_Config.ipv4_local_subnet,
|
||||
&Global_Clatd_Config.plat_subnet);
|
||||
} else {
|
||||
/* Use the specified interface ID. */
|
||||
for(i = 2; i < 4; i++) {
|
||||
for (i = 2; i < 4; i++) {
|
||||
interface_ip->s6_addr32[i] = Global_Clatd_Config.ipv6_host_id.s6_addr32[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* function: read_config
|
||||
* reads the config file and parses it into the global variable Global_Clatd_Config. returns 0 on failure, 1 on success
|
||||
* file - filename to parse
|
||||
* uplink_interface - interface to use to reach the internet and supplier of address space
|
||||
* plat_prefix - (optional) plat prefix to use, otherwise follow config file
|
||||
* net_id - (optional) netId to use, NETID_UNSET indicates use of default network
|
||||
* reads the config file and parses it into the global variable Global_Clatd_Config. returns 0 on
|
||||
* failure, 1 on success
|
||||
* file - filename to parse
|
||||
* uplink_interface - interface to use to reach the internet and supplier of address space
|
||||
* plat_prefix - (optional) plat prefix to use, otherwise follow config file
|
||||
* net_id - (optional) netId to use, NETID_UNSET indicates use of default network
|
||||
*/
|
||||
int read_config(const char *file, const char *uplink_interface, const char *plat_prefix,
|
||||
unsigned net_id) {
|
||||
cnode *root = config_node("", "");
|
||||
unsigned net_id) {
|
||||
cnode *root = config_node("", "");
|
||||
void *tmp_ptr = NULL;
|
||||
unsigned flags;
|
||||
|
||||
if(!root) {
|
||||
logmsg(ANDROID_LOG_FATAL,"out of memory");
|
||||
if (!root) {
|
||||
logmsg(ANDROID_LOG_FATAL, "out of memory");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&Global_Clatd_Config, '\0', sizeof(Global_Clatd_Config));
|
||||
|
||||
config_load_file(root, file);
|
||||
if(root->first_child == NULL) {
|
||||
logmsg(ANDROID_LOG_FATAL,"Could not read config file %s", file);
|
||||
if (root->first_child == NULL) {
|
||||
logmsg(ANDROID_LOG_FATAL, "Could not read config file %s", file);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
Global_Clatd_Config.default_pdp_interface = strdup(uplink_interface);
|
||||
if (!Global_Clatd_Config.default_pdp_interface)
|
||||
if (!Global_Clatd_Config.default_pdp_interface) goto failed;
|
||||
|
||||
if (!config_item_int16_t(root, "mtu", "-1", &Global_Clatd_Config.mtu)) goto failed;
|
||||
|
||||
if (!config_item_int16_t(root, "ipv4mtu", "-1", &Global_Clatd_Config.ipv4mtu)) goto failed;
|
||||
|
||||
if (!config_item_ip(root, "ipv4_local_subnet", DEFAULT_IPV4_LOCAL_SUBNET,
|
||||
&Global_Clatd_Config.ipv4_local_subnet))
|
||||
goto failed;
|
||||
|
||||
if(!config_item_int16_t(root, "mtu", "-1", &Global_Clatd_Config.mtu))
|
||||
if (!config_item_int16_t(root, "ipv4_local_prefixlen", DEFAULT_IPV4_LOCAL_PREFIXLEN,
|
||||
&Global_Clatd_Config.ipv4_local_prefixlen))
|
||||
goto failed;
|
||||
|
||||
if(!config_item_int16_t(root, "ipv4mtu", "-1", &Global_Clatd_Config.ipv4mtu))
|
||||
goto failed;
|
||||
|
||||
if(!config_item_ip(root, "ipv4_local_subnet", DEFAULT_IPV4_LOCAL_SUBNET,
|
||||
&Global_Clatd_Config.ipv4_local_subnet))
|
||||
goto failed;
|
||||
|
||||
if(!config_item_int16_t(root, "ipv4_local_prefixlen", DEFAULT_IPV4_LOCAL_PREFIXLEN,
|
||||
&Global_Clatd_Config.ipv4_local_prefixlen))
|
||||
goto failed;
|
||||
|
||||
if(plat_prefix) { // plat subnet is coming from the command line
|
||||
if(inet_pton(AF_INET6, plat_prefix, &Global_Clatd_Config.plat_subnet) <= 0) {
|
||||
logmsg(ANDROID_LOG_FATAL,"invalid IPv6 address specified for plat prefix: %s", plat_prefix);
|
||||
if (plat_prefix) { // plat subnet is coming from the command line
|
||||
if (inet_pton(AF_INET6, plat_prefix, &Global_Clatd_Config.plat_subnet) <= 0) {
|
||||
logmsg(ANDROID_LOG_FATAL, "invalid IPv6 address specified for plat prefix: %s", plat_prefix);
|
||||
goto failed;
|
||||
}
|
||||
} else {
|
||||
tmp_ptr = (void *)config_item_str(root, "plat_from_dns64", "yes");
|
||||
if(!tmp_ptr || strcmp(tmp_ptr, "no") == 0) {
|
||||
if (!tmp_ptr || strcmp(tmp_ptr, "no") == 0) {
|
||||
free(tmp_ptr);
|
||||
|
||||
if(!config_item_ip6(root, "plat_subnet", NULL, &Global_Clatd_Config.plat_subnet)) {
|
||||
if (!config_item_ip6(root, "plat_subnet", NULL, &Global_Clatd_Config.plat_subnet)) {
|
||||
logmsg(ANDROID_LOG_FATAL, "plat_from_dns64 disabled, but no plat_subnet specified");
|
||||
goto failed;
|
||||
}
|
||||
} else {
|
||||
free(tmp_ptr);
|
||||
|
||||
if(!(Global_Clatd_Config.plat_from_dns64_hostname = config_item_str(root, "plat_from_dns64_hostname", DEFAULT_DNS64_DETECTION_HOSTNAME)))
|
||||
if (!(Global_Clatd_Config.plat_from_dns64_hostname =
|
||||
config_item_str(root, "plat_from_dns64_hostname", DEFAULT_DNS64_DETECTION_HOSTNAME)))
|
||||
goto failed;
|
||||
dns64_detection(net_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (!config_item_ip6(root, "ipv6_host_id", "::", &Global_Clatd_Config.ipv6_host_id))
|
||||
goto failed;
|
||||
if (!config_item_ip6(root, "ipv6_host_id", "::", &Global_Clatd_Config.ipv6_host_id)) goto failed;
|
||||
|
||||
/* In order to prevent multiple devices attempting to use the same clat address, never use a
|
||||
statically-configured interface ID on a broadcast interface such as wifi. */
|
||||
|
|
@ -388,11 +391,17 @@ failed:
|
|||
void dump_config() {
|
||||
char charbuffer[INET6_ADDRSTRLEN];
|
||||
|
||||
logmsg(ANDROID_LOG_DEBUG,"mtu = %d",Global_Clatd_Config.mtu);
|
||||
logmsg(ANDROID_LOG_DEBUG,"ipv4mtu = %d",Global_Clatd_Config.ipv4mtu);
|
||||
logmsg(ANDROID_LOG_DEBUG,"ipv6_local_subnet = %s",inet_ntop(AF_INET6, &Global_Clatd_Config.ipv6_local_subnet, charbuffer, sizeof(charbuffer)));
|
||||
logmsg(ANDROID_LOG_DEBUG,"ipv4_local_subnet = %s",inet_ntop(AF_INET, &Global_Clatd_Config.ipv4_local_subnet, charbuffer, sizeof(charbuffer)));
|
||||
logmsg(ANDROID_LOG_DEBUG,"ipv4_local_prefixlen = %d", Global_Clatd_Config.ipv4_local_prefixlen);
|
||||
logmsg(ANDROID_LOG_DEBUG,"plat_subnet = %s",inet_ntop(AF_INET6, &Global_Clatd_Config.plat_subnet, charbuffer, sizeof(charbuffer)));
|
||||
logmsg(ANDROID_LOG_DEBUG,"default_pdp_interface = %s",Global_Clatd_Config.default_pdp_interface);
|
||||
logmsg(ANDROID_LOG_DEBUG, "mtu = %d", Global_Clatd_Config.mtu);
|
||||
logmsg(ANDROID_LOG_DEBUG, "ipv4mtu = %d", Global_Clatd_Config.ipv4mtu);
|
||||
logmsg(
|
||||
ANDROID_LOG_DEBUG, "ipv6_local_subnet = %s",
|
||||
inet_ntop(AF_INET6, &Global_Clatd_Config.ipv6_local_subnet, charbuffer, sizeof(charbuffer)));
|
||||
logmsg(
|
||||
ANDROID_LOG_DEBUG, "ipv4_local_subnet = %s",
|
||||
inet_ntop(AF_INET, &Global_Clatd_Config.ipv4_local_subnet, charbuffer, sizeof(charbuffer)));
|
||||
logmsg(ANDROID_LOG_DEBUG, "ipv4_local_prefixlen = %d", Global_Clatd_Config.ipv4_local_prefixlen);
|
||||
logmsg(ANDROID_LOG_DEBUG, "plat_subnet = %s",
|
||||
inet_ntop(AF_INET6, &Global_Clatd_Config.plat_subnet, charbuffer, sizeof(charbuffer)));
|
||||
logmsg(ANDROID_LOG_DEBUG, "default_pdp_interface = %s",
|
||||
Global_Clatd_Config.default_pdp_interface);
|
||||
}
|
||||
|
|
|
|||
4
config.h
4
config.h
|
|
@ -18,8 +18,8 @@
|
|||
#ifndef __CONFIG_H__
|
||||
#define __CONFIG_H__
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <linux/if.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#define DEFAULT_IPV4_LOCAL_SUBNET "192.0.0.4"
|
||||
#define DEFAULT_IPV4_LOCAL_PREFIXLEN "29"
|
||||
|
|
@ -40,7 +40,7 @@ struct clat_config {
|
|||
extern struct clat_config Global_Clatd_Config;
|
||||
|
||||
int read_config(const char *file, const char *uplink_interface, const char *plat_prefix,
|
||||
unsigned net_id);
|
||||
unsigned net_id);
|
||||
void config_generate_local_ipv6_subnet(struct in6_addr *interface_ip);
|
||||
in_addr_t config_select_ipv4_address(const struct in_addr *ip, int16_t prefixlen);
|
||||
int ipv6_prefix_equal(struct in6_addr *a1, struct in6_addr *a2);
|
||||
|
|
|
|||
21
dns64.c
21
dns64.c
|
|
@ -16,25 +16,26 @@
|
|||
* dns64.c - find the nat64 prefix with a dns64 lookup
|
||||
*/
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <strings.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "NetdClient.h"
|
||||
#include "dns64.h"
|
||||
#include "logging.h"
|
||||
#include "NetdClient.h"
|
||||
#include "resolv_netid.h"
|
||||
|
||||
/* function: plat_prefix
|
||||
* looks up an ipv4-only hostname and looks for a nat64 /96 prefix, returns 1 on success, 0 on failure
|
||||
* ipv4_name - name to lookup
|
||||
* net_id - (optional) netId to use, NETID_UNSET indicates use of default network
|
||||
* prefix - the plat /96 prefix
|
||||
* looks up an ipv4-only hostname and looks for a nat64 /96 prefix, returns 1 on success, 0 on
|
||||
* failure
|
||||
* ipv4_name - name to lookup
|
||||
* net_id - (optional) netId to use, NETID_UNSET indicates use of default network
|
||||
* prefix - the plat /96 prefix
|
||||
*/
|
||||
int plat_prefix(const char *ipv4_name, unsigned net_id, struct in6_addr *prefix) {
|
||||
const struct addrinfo hints = {
|
||||
|
|
@ -54,8 +55,8 @@ int plat_prefix(const char *ipv4_name, unsigned net_id, struct in6_addr *prefix)
|
|||
|
||||
status = android_getaddrinfofornet(ipv4_name, NULL, &hints, net_id, MARK_UNSET, &result);
|
||||
if (status != 0 || result == NULL) {
|
||||
logmsg(ANDROID_LOG_ERROR, "plat_prefix/dns(%s) status = %d/%s",
|
||||
ipv4_name, status, gai_strerror(status));
|
||||
logmsg(ANDROID_LOG_ERROR, "plat_prefix/dns(%s) status = %d/%s", ipv4_name, status,
|
||||
gai_strerror(status));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
176
dump.c
176
dump.c
|
|
@ -15,23 +15,23 @@
|
|||
*
|
||||
* dump.c - print various headers for debugging
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/icmp.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <linux/icmp.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "checksum.h"
|
||||
#include "clatd.h"
|
||||
#include "debug.h"
|
||||
#include "logging.h"
|
||||
|
||||
#if CLAT_DEBUG
|
||||
|
|
@ -44,29 +44,29 @@ void dump_ip(struct iphdr *header) {
|
|||
frag_flags = ntohs(header->frag_off);
|
||||
|
||||
printf("IP packet\n");
|
||||
printf("header_len = %x\n",header->ihl);
|
||||
printf("version = %x\n",header->version);
|
||||
printf("tos = %x\n",header->tos);
|
||||
printf("tot_len = %x\n",ntohs(header->tot_len));
|
||||
printf("id = %x\n",ntohs(header->id));
|
||||
printf("header_len = %x\n", header->ihl);
|
||||
printf("version = %x\n", header->version);
|
||||
printf("tos = %x\n", header->tos);
|
||||
printf("tot_len = %x\n", ntohs(header->tot_len));
|
||||
printf("id = %x\n", ntohs(header->id));
|
||||
printf("frag: ");
|
||||
if(frag_flags & IP_RF) {
|
||||
if (frag_flags & IP_RF) {
|
||||
printf("(RF) ");
|
||||
}
|
||||
if(frag_flags & IP_DF) {
|
||||
if (frag_flags & IP_DF) {
|
||||
printf("DF ");
|
||||
}
|
||||
if(frag_flags & IP_MF) {
|
||||
if (frag_flags & IP_MF) {
|
||||
printf("MF ");
|
||||
}
|
||||
printf("offset = %x\n",frag_flags & IP_OFFMASK);
|
||||
printf("ttl = %x\n",header->ttl);
|
||||
printf("protocol = %x\n",header->protocol);
|
||||
printf("checksum = %x\n",ntohs(header->check));
|
||||
printf("offset = %x\n", frag_flags & IP_OFFMASK);
|
||||
printf("ttl = %x\n", header->ttl);
|
||||
printf("protocol = %x\n", header->protocol);
|
||||
printf("checksum = %x\n", ntohs(header->check));
|
||||
inet_ntop(AF_INET, &header->saddr, addrstr, sizeof(addrstr));
|
||||
printf("saddr = %s\n",addrstr);
|
||||
printf("saddr = %s\n", addrstr);
|
||||
inet_ntop(AF_INET, &header->daddr, addrstr, sizeof(addrstr));
|
||||
printf("daddr = %s\n",addrstr);
|
||||
printf("daddr = %s\n", addrstr);
|
||||
}
|
||||
|
||||
/* print ip6 header */
|
||||
|
|
@ -74,138 +74,138 @@ void dump_ip6(struct ip6_hdr *header) {
|
|||
char addrstr[INET6_ADDRSTRLEN];
|
||||
|
||||
printf("ipv6\n");
|
||||
printf("version = %x\n",header->ip6_vfc >> 4);
|
||||
printf("traffic class = %x\n",header->ip6_flow >> 20);
|
||||
printf("flow label = %x\n",ntohl(header->ip6_flow & 0x000fffff));
|
||||
printf("payload len = %x\n",ntohs(header->ip6_plen));
|
||||
printf("next header = %x\n",header->ip6_nxt);
|
||||
printf("hop limit = %x\n",header->ip6_hlim);
|
||||
printf("version = %x\n", header->ip6_vfc >> 4);
|
||||
printf("traffic class = %x\n", header->ip6_flow >> 20);
|
||||
printf("flow label = %x\n", ntohl(header->ip6_flow & 0x000fffff));
|
||||
printf("payload len = %x\n", ntohs(header->ip6_plen));
|
||||
printf("next header = %x\n", header->ip6_nxt);
|
||||
printf("hop limit = %x\n", header->ip6_hlim);
|
||||
|
||||
inet_ntop(AF_INET6, &header->ip6_src, addrstr, sizeof(addrstr));
|
||||
printf("source = %s\n",addrstr);
|
||||
printf("source = %s\n", addrstr);
|
||||
|
||||
inet_ntop(AF_INET6, &header->ip6_dst, addrstr, sizeof(addrstr));
|
||||
printf("dest = %s\n",addrstr);
|
||||
printf("dest = %s\n", addrstr);
|
||||
}
|
||||
|
||||
/* print icmp header */
|
||||
void dump_icmp(struct icmphdr *icmp) {
|
||||
printf("ICMP\n");
|
||||
|
||||
printf("icmp.type = %x ",icmp->type);
|
||||
if(icmp->type == ICMP_ECHOREPLY) {
|
||||
printf("icmp.type = %x ", icmp->type);
|
||||
if (icmp->type == ICMP_ECHOREPLY) {
|
||||
printf("echo reply");
|
||||
} else if(icmp->type == ICMP_ECHO) {
|
||||
} else if (icmp->type == ICMP_ECHO) {
|
||||
printf("echo request");
|
||||
} else {
|
||||
printf("other");
|
||||
}
|
||||
printf("\n");
|
||||
printf("icmp.code = %x\n",icmp->code);
|
||||
printf("icmp.checksum = %x\n",ntohs(icmp->checksum));
|
||||
if(icmp->type == ICMP_ECHOREPLY || icmp->type == ICMP_ECHO) {
|
||||
printf("icmp.un.echo.id = %x\n",ntohs(icmp->un.echo.id));
|
||||
printf("icmp.un.echo.sequence = %x\n",ntohs(icmp->un.echo.sequence));
|
||||
printf("icmp.code = %x\n", icmp->code);
|
||||
printf("icmp.checksum = %x\n", ntohs(icmp->checksum));
|
||||
if (icmp->type == ICMP_ECHOREPLY || icmp->type == ICMP_ECHO) {
|
||||
printf("icmp.un.echo.id = %x\n", ntohs(icmp->un.echo.id));
|
||||
printf("icmp.un.echo.sequence = %x\n", ntohs(icmp->un.echo.sequence));
|
||||
}
|
||||
}
|
||||
|
||||
/* print icmp6 header */
|
||||
void dump_icmp6(struct icmp6_hdr *icmp6) {
|
||||
printf("ICMP6\n");
|
||||
printf("type = %x",icmp6->icmp6_type);
|
||||
if(icmp6->icmp6_type == ICMP6_ECHO_REQUEST) {
|
||||
printf("type = %x", icmp6->icmp6_type);
|
||||
if (icmp6->icmp6_type == ICMP6_ECHO_REQUEST) {
|
||||
printf("(echo request)");
|
||||
} else if(icmp6->icmp6_type == ICMP6_ECHO_REPLY) {
|
||||
} else if (icmp6->icmp6_type == ICMP6_ECHO_REPLY) {
|
||||
printf("(echo reply)");
|
||||
}
|
||||
printf("\n");
|
||||
printf("code = %x\n",icmp6->icmp6_code);
|
||||
printf("code = %x\n", icmp6->icmp6_code);
|
||||
|
||||
printf("checksum = %x\n",icmp6->icmp6_cksum);
|
||||
printf("checksum = %x\n", icmp6->icmp6_cksum);
|
||||
|
||||
if((icmp6->icmp6_type == ICMP6_ECHO_REQUEST) || (icmp6->icmp6_type == ICMP6_ECHO_REPLY)) {
|
||||
printf("icmp6_id = %x\n",icmp6->icmp6_id);
|
||||
printf("icmp6_seq = %x\n",icmp6->icmp6_seq);
|
||||
if ((icmp6->icmp6_type == ICMP6_ECHO_REQUEST) || (icmp6->icmp6_type == ICMP6_ECHO_REPLY)) {
|
||||
printf("icmp6_id = %x\n", icmp6->icmp6_id);
|
||||
printf("icmp6_seq = %x\n", icmp6->icmp6_seq);
|
||||
}
|
||||
}
|
||||
|
||||
/* print udp header */
|
||||
void dump_udp_generic(const struct udphdr *udp, uint32_t temp_checksum,
|
||||
const uint8_t *payload, size_t payload_size) {
|
||||
void dump_udp_generic(const struct udphdr *udp, uint32_t temp_checksum, const uint8_t *payload,
|
||||
size_t payload_size) {
|
||||
uint16_t my_checksum;
|
||||
|
||||
temp_checksum = ip_checksum_add(temp_checksum, udp, sizeof(struct udphdr));
|
||||
temp_checksum = ip_checksum_add(temp_checksum, payload, payload_size);
|
||||
my_checksum = ip_checksum_finish(temp_checksum);
|
||||
my_checksum = ip_checksum_finish(temp_checksum);
|
||||
|
||||
printf("UDP\n");
|
||||
printf("source = %x\n",ntohs(udp->source));
|
||||
printf("dest = %x\n",ntohs(udp->dest));
|
||||
printf("len = %x\n",ntohs(udp->len));
|
||||
printf("check = %x (mine %x)\n",udp->check,my_checksum);
|
||||
printf("source = %x\n", ntohs(udp->source));
|
||||
printf("dest = %x\n", ntohs(udp->dest));
|
||||
printf("len = %x\n", ntohs(udp->len));
|
||||
printf("check = %x (mine %x)\n", udp->check, my_checksum);
|
||||
}
|
||||
|
||||
/* print ipv4/udp header */
|
||||
void dump_udp(const struct udphdr *udp, const struct iphdr *ip,
|
||||
const uint8_t *payload, size_t payload_size) {
|
||||
void dump_udp(const struct udphdr *udp, const struct iphdr *ip, const uint8_t *payload,
|
||||
size_t payload_size) {
|
||||
uint32_t temp_checksum;
|
||||
temp_checksum = ipv4_pseudo_header_checksum(ip, sizeof(*udp) + payload_size);
|
||||
dump_udp_generic(udp, temp_checksum, payload, payload_size);
|
||||
}
|
||||
|
||||
/* print ipv6/udp header */
|
||||
void dump_udp6(const struct udphdr *udp, const struct ip6_hdr *ip6,
|
||||
const uint8_t *payload, size_t payload_size) {
|
||||
void dump_udp6(const struct udphdr *udp, const struct ip6_hdr *ip6, const uint8_t *payload,
|
||||
size_t payload_size) {
|
||||
uint32_t temp_checksum;
|
||||
temp_checksum = ipv6_pseudo_header_checksum(ip6, sizeof(*udp) + payload_size, IPPROTO_UDP);
|
||||
dump_udp_generic(udp, temp_checksum, payload, payload_size);
|
||||
}
|
||||
|
||||
/* print tcp header */
|
||||
void dump_tcp_generic(const struct tcphdr *tcp, const uint8_t *options, size_t options_size, uint32_t temp_checksum, const uint8_t *payload, size_t payload_size) {
|
||||
void dump_tcp_generic(const struct tcphdr *tcp, const uint8_t *options, size_t options_size,
|
||||
uint32_t temp_checksum, const uint8_t *payload, size_t payload_size) {
|
||||
uint16_t my_checksum;
|
||||
|
||||
temp_checksum = ip_checksum_add(temp_checksum, tcp, sizeof(struct tcphdr));
|
||||
if(options) {
|
||||
if (options) {
|
||||
temp_checksum = ip_checksum_add(temp_checksum, options, options_size);
|
||||
}
|
||||
temp_checksum = ip_checksum_add(temp_checksum, payload, payload_size);
|
||||
my_checksum = ip_checksum_finish(temp_checksum);
|
||||
my_checksum = ip_checksum_finish(temp_checksum);
|
||||
|
||||
printf("TCP\n");
|
||||
printf("source = %x\n",ntohs(tcp->source));
|
||||
printf("dest = %x\n",ntohs(tcp->dest));
|
||||
printf("seq = %x\n",ntohl(tcp->seq));
|
||||
printf("ack = %x\n",ntohl(tcp->ack_seq));
|
||||
printf("d_off = %x\n",tcp->doff);
|
||||
printf("res1 = %x\n",tcp->res1);
|
||||
printf("source = %x\n", ntohs(tcp->source));
|
||||
printf("dest = %x\n", ntohs(tcp->dest));
|
||||
printf("seq = %x\n", ntohl(tcp->seq));
|
||||
printf("ack = %x\n", ntohl(tcp->ack_seq));
|
||||
printf("d_off = %x\n", tcp->doff);
|
||||
printf("res1 = %x\n", tcp->res1);
|
||||
#ifdef __BIONIC__
|
||||
printf("CWR = %x\n",tcp->cwr);
|
||||
printf("ECE = %x\n",tcp->ece);
|
||||
printf("CWR = %x\n", tcp->cwr);
|
||||
printf("ECE = %x\n", tcp->ece);
|
||||
#else
|
||||
printf("CWR/ECE = %x\n",tcp->res2);
|
||||
printf("CWR/ECE = %x\n", tcp->res2);
|
||||
#endif
|
||||
printf("urg = %x ack = %x psh = %x rst = %x syn = %x fin = %x\n",
|
||||
tcp->urg, tcp->ack, tcp->psh, tcp->rst, tcp->syn, tcp->fin);
|
||||
printf("window = %x\n",ntohs(tcp->window));
|
||||
printf("check = %x [mine %x]\n",tcp->check,my_checksum);
|
||||
printf("urgent = %x\n",tcp->urg_ptr);
|
||||
printf("urg = %x ack = %x psh = %x rst = %x syn = %x fin = %x\n", tcp->urg, tcp->ack,
|
||||
tcp->psh, tcp->rst, tcp->syn, tcp->fin);
|
||||
printf("window = %x\n", ntohs(tcp->window));
|
||||
printf("check = %x [mine %x]\n", tcp->check, my_checksum);
|
||||
printf("urgent = %x\n", tcp->urg_ptr);
|
||||
|
||||
if(options) {
|
||||
if (options) {
|
||||
size_t i;
|
||||
|
||||
printf("options: ");
|
||||
for(i=0; i<options_size; i++) {
|
||||
printf("%x ",*(options+i));
|
||||
for (i = 0; i < options_size; i++) {
|
||||
printf("%x ", *(options + i));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* print ipv4/tcp header */
|
||||
void dump_tcp(const struct tcphdr *tcp, const struct iphdr *ip,
|
||||
const uint8_t *payload, size_t payload_size,
|
||||
const uint8_t *options, size_t options_size) {
|
||||
void dump_tcp(const struct tcphdr *tcp, const struct iphdr *ip, const uint8_t *payload,
|
||||
size_t payload_size, const uint8_t *options, size_t options_size) {
|
||||
uint32_t temp_checksum;
|
||||
|
||||
temp_checksum = ipv4_pseudo_header_checksum(ip, sizeof(*tcp) + options_size + payload_size);
|
||||
|
|
@ -213,27 +213,27 @@ void dump_tcp(const struct tcphdr *tcp, const struct iphdr *ip,
|
|||
}
|
||||
|
||||
/* print ipv6/tcp header */
|
||||
void dump_tcp6(const struct tcphdr *tcp, const struct ip6_hdr *ip6,
|
||||
const uint8_t *payload, size_t payload_size,
|
||||
const uint8_t *options, size_t options_size) {
|
||||
void dump_tcp6(const struct tcphdr *tcp, const struct ip6_hdr *ip6, const uint8_t *payload,
|
||||
size_t payload_size, const uint8_t *options, size_t options_size) {
|
||||
uint32_t temp_checksum;
|
||||
|
||||
temp_checksum = ipv6_pseudo_header_checksum(ip6, sizeof(*tcp) + options_size + payload_size, IPPROTO_TCP);
|
||||
temp_checksum =
|
||||
ipv6_pseudo_header_checksum(ip6, sizeof(*tcp) + options_size + payload_size, IPPROTO_TCP);
|
||||
dump_tcp_generic(tcp, options, options_size, temp_checksum, payload, payload_size);
|
||||
}
|
||||
|
||||
/* generic hex dump */
|
||||
void logcat_hexdump(const char *info, const uint8_t *data, size_t len) {
|
||||
char output[PACKETLEN*3+2];
|
||||
char output[PACKETLEN * 3 + 2];
|
||||
size_t i;
|
||||
|
||||
output[0] = '\0';
|
||||
for(i = 0; i < len && i < PACKETLEN; i++) {
|
||||
snprintf(output + i*3, 4, " %02x", data[i]);
|
||||
for (i = 0; i < len && i < PACKETLEN; i++) {
|
||||
snprintf(output + i * 3, 4, " %02x", data[i]);
|
||||
}
|
||||
output[len*3+3] = '\0';
|
||||
output[len * 3 + 3] = '\0';
|
||||
|
||||
logmsg(ANDROID_LOG_WARN,"info %s len %d data%s", info, len, output);
|
||||
logmsg(ANDROID_LOG_WARN, "info %s len %d data%s", info, len, output);
|
||||
}
|
||||
|
||||
void dump_iovec(const struct iovec *iov, int iov_len) {
|
||||
|
|
|
|||
26
dump.h
26
dump.h
|
|
@ -18,21 +18,27 @@
|
|||
#ifndef __DUMP_H__
|
||||
#define __DUMP_H__
|
||||
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
|
||||
void dump_ip(struct iphdr *header);
|
||||
void dump_icmp(struct icmphdr *icmp);
|
||||
void dump_udp(const struct udphdr *udp, const struct iphdr *ip,
|
||||
const uint8_t *payload, size_t payload_size);
|
||||
void dump_tcp(const struct tcphdr *tcp, const struct iphdr *ip,
|
||||
const uint8_t *payload, size_t payload_size,
|
||||
const char *options, size_t options_size);
|
||||
void dump_udp(const struct udphdr *udp, const struct iphdr *ip, const uint8_t *payload,
|
||||
size_t payload_size);
|
||||
void dump_tcp(const struct tcphdr *tcp, const struct iphdr *ip, const uint8_t *payload,
|
||||
size_t payload_size, const char *options, size_t options_size);
|
||||
|
||||
void dump_ip6(struct ip6_hdr *header);
|
||||
void dump_icmp6(struct icmp6_hdr *icmp6);
|
||||
void dump_udp6(const struct udphdr *udp, const struct ip6_hdr *ip6,
|
||||
const uint8_t *payload, size_t payload_size);
|
||||
void dump_tcp6(const struct tcphdr *tcp, const struct ip6_hdr *ip6,
|
||||
const uint8_t *payload, size_t payload_size,
|
||||
const char *options, size_t options_size);
|
||||
void dump_udp6(const struct udphdr *udp, const struct ip6_hdr *ip6, const uint8_t *payload,
|
||||
size_t payload_size);
|
||||
void dump_tcp6(const struct tcphdr *tcp, const struct ip6_hdr *ip6, const uint8_t *payload,
|
||||
size_t payload_size, const char *options, size_t options_size);
|
||||
|
||||
void logcat_hexdump(const char *info, const uint8_t *data, size_t len);
|
||||
void dump_iovec(const struct iovec *iov, int iov_len);
|
||||
|
|
|
|||
54
getaddr.c
54
getaddr.c
|
|
@ -15,10 +15,10 @@
|
|||
*
|
||||
* getaddr.c - get a locally configured address
|
||||
*/
|
||||
#include <netinet/in.h>
|
||||
#include <strings.h>
|
||||
#include <string.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include <linux/if_addr.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
|
|
@ -26,8 +26,8 @@
|
|||
#include <netlink/msg.h>
|
||||
|
||||
#include "getaddr.h"
|
||||
#include "netlink_msg.h"
|
||||
#include "logging.h"
|
||||
#include "netlink_msg.h"
|
||||
|
||||
// shared state between getinterface_ip and getaddr_cb
|
||||
struct target {
|
||||
|
|
@ -39,8 +39,8 @@ struct target {
|
|||
|
||||
/* function: getaddr_cb
|
||||
* callback for getinterface_ip
|
||||
* msg - netlink message
|
||||
* data - (struct target) info for which address we're looking for
|
||||
* msg - netlink message
|
||||
* data - (struct target) info for which address we're looking for
|
||||
*/
|
||||
static int getaddr_cb(struct nl_msg *msg, void *data) {
|
||||
struct ifaddrmsg *ifa_p;
|
||||
|
|
@ -51,24 +51,22 @@ static int getaddr_cb(struct nl_msg *msg, void *data) {
|
|||
ifa_p = (struct ifaddrmsg *)nlmsg_data(nlmsg_hdr(msg));
|
||||
rta_p = (struct rtattr *)IFA_RTA(ifa_p);
|
||||
|
||||
if(ifa_p->ifa_index != targ_p->ifindex)
|
||||
return NL_OK;
|
||||
if (ifa_p->ifa_index != targ_p->ifindex) return NL_OK;
|
||||
|
||||
if(ifa_p->ifa_scope != RT_SCOPE_UNIVERSE)
|
||||
return NL_OK;
|
||||
if (ifa_p->ifa_scope != RT_SCOPE_UNIVERSE) return NL_OK;
|
||||
|
||||
rta_len = RTM_PAYLOAD(nlmsg_hdr(msg));
|
||||
for (; RTA_OK(rta_p, rta_len); rta_p = RTA_NEXT(rta_p, rta_len)) {
|
||||
switch(rta_p->rta_type) {
|
||||
switch (rta_p->rta_type) {
|
||||
case IFA_ADDRESS:
|
||||
if((targ_p->family == AF_INET6) && !(ifa_p->ifa_flags & IFA_F_SECONDARY)) {
|
||||
if ((targ_p->family == AF_INET6) && !(ifa_p->ifa_flags & IFA_F_SECONDARY)) {
|
||||
memcpy(&targ_p->ip.ip6, RTA_DATA(rta_p), rta_p->rta_len - sizeof(struct rtattr));
|
||||
targ_p->foundip = 1;
|
||||
return NL_OK;
|
||||
}
|
||||
break;
|
||||
case IFA_LOCAL:
|
||||
if(targ_p->family == AF_INET) {
|
||||
if (targ_p->family == AF_INET) {
|
||||
memcpy(&targ_p->ip.ip4, RTA_DATA(rta_p), rta_p->rta_len - sizeof(struct rtattr));
|
||||
targ_p->foundip = 1;
|
||||
return NL_OK;
|
||||
|
|
@ -82,9 +80,9 @@ static int getaddr_cb(struct nl_msg *msg, void *data) {
|
|||
|
||||
/* function: error_handler
|
||||
* error callback for getinterface_ip
|
||||
* nla - source of the error message
|
||||
* err - netlink message
|
||||
* arg - (struct target) info for which address we're looking for
|
||||
* nla - source of the error message
|
||||
* err - netlink message
|
||||
* arg - (struct target) info for which address we're looking for
|
||||
*/
|
||||
static int error_handler(__attribute__((unused)) struct sockaddr_nl *nla,
|
||||
__attribute__((unused)) struct nlmsgerr *err,
|
||||
|
|
@ -93,9 +91,10 @@ static int error_handler(__attribute__((unused)) struct sockaddr_nl *nla,
|
|||
}
|
||||
|
||||
/* function: getinterface_ip
|
||||
* finds the first global non-privacy IP of the given family for the given interface, or returns NULL. caller frees pointer
|
||||
* interface - interface to look for
|
||||
* family - family
|
||||
* finds the first global non-privacy IP of the given family for the given interface, or returns
|
||||
* NULL. caller frees pointer
|
||||
* interface - interface to look for
|
||||
* family - family
|
||||
*/
|
||||
union anyip *getinterface_ip(const char *interface, int family) {
|
||||
struct ifaddrmsg ifa;
|
||||
|
|
@ -103,18 +102,18 @@ union anyip *getinterface_ip(const char *interface, int family) {
|
|||
struct target targ;
|
||||
union anyip *retval = NULL;
|
||||
|
||||
targ.family = family;
|
||||
targ.family = family;
|
||||
targ.foundip = 0;
|
||||
targ.ifindex = if_nametoindex(interface);
|
||||
if(targ.ifindex == 0) {
|
||||
return NULL; // interface not found
|
||||
if (targ.ifindex == 0) {
|
||||
return NULL; // interface not found
|
||||
}
|
||||
|
||||
memset(&ifa, 0, sizeof(ifa));
|
||||
ifa.ifa_family = targ.family;
|
||||
|
||||
callbacks = nl_cb_alloc(NL_CB_DEFAULT);
|
||||
if(!callbacks) {
|
||||
if (!callbacks) {
|
||||
goto cleanup;
|
||||
}
|
||||
nl_cb_set(callbacks, NL_CB_VALID, NL_CB_CUSTOM, getaddr_cb, &targ);
|
||||
|
|
@ -123,18 +122,17 @@ union anyip *getinterface_ip(const char *interface, int family) {
|
|||
// sends message and waits for a response
|
||||
send_ifaddrmsg(RTM_GETADDR, NLM_F_REQUEST | NLM_F_ROOT, &ifa, callbacks);
|
||||
|
||||
if(targ.foundip) {
|
||||
if (targ.foundip) {
|
||||
retval = malloc(sizeof(union anyip));
|
||||
if(!retval) {
|
||||
logmsg(ANDROID_LOG_FATAL,"getinterface_ip/out of memory");
|
||||
if (!retval) {
|
||||
logmsg(ANDROID_LOG_FATAL, "getinterface_ip/out of memory");
|
||||
goto cleanup;
|
||||
}
|
||||
memcpy(retval, &targ.ip, sizeof(union anyip));
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if(callbacks)
|
||||
nl_cb_put(callbacks);
|
||||
if (callbacks) nl_cb_put(callbacks);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
|
|||
18
icmp.c
18
icmp.c
|
|
@ -16,13 +16,13 @@
|
|||
* icmp.c - convenience functions for translating ICMP and ICMPv6 packets.
|
||||
*/
|
||||
|
||||
#include <linux/icmp.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <linux/icmp.h>
|
||||
|
||||
#include "logging.h"
|
||||
#include "icmp.h"
|
||||
#include "logging.h"
|
||||
|
||||
/* function: icmp_guess_ttl
|
||||
* Guesses the number of hops a received packet has traversed based on its TTL.
|
||||
|
|
@ -44,17 +44,13 @@ uint8_t icmp_guess_ttl(uint8_t ttl) {
|
|||
* Determines whether an ICMP type is an error message.
|
||||
* type: the ICMP type
|
||||
*/
|
||||
int is_icmp_error(uint8_t type) {
|
||||
return type == 3 || type == 11 || type == 12;
|
||||
}
|
||||
int is_icmp_error(uint8_t type) { return type == 3 || type == 11 || type == 12; }
|
||||
|
||||
/* function: is_icmp6_error
|
||||
* Determines whether an ICMPv6 type is an error message.
|
||||
* type: the ICMPv6 type
|
||||
*/
|
||||
int is_icmp6_error(uint8_t type) {
|
||||
return type < 128;
|
||||
}
|
||||
int is_icmp6_error(uint8_t type) { return type < 128; }
|
||||
|
||||
/* function: icmp_to_icmp6_type
|
||||
* Maps ICMP types to ICMPv6 types. Partial implementation of RFC 6145, section 4.2.
|
||||
|
|
@ -112,7 +108,7 @@ uint8_t icmp_to_icmp6_code(uint8_t type, uint8_t code) {
|
|||
case ICMP_UNREACH_PRECEDENCE_CUTOFF:
|
||||
return ICMP6_DST_UNREACH_ADMIN;
|
||||
|
||||
// Otherwise, we don't understand this ICMP type/code combination. Fall through.
|
||||
// Otherwise, we don't understand this ICMP type/code combination. Fall through.
|
||||
}
|
||||
}
|
||||
logmsg_dbg(ANDROID_LOG_DEBUG, "icmp_to_icmp6_code: unhandled ICMP type/code %d/%d", type, code);
|
||||
|
|
@ -172,7 +168,7 @@ uint8_t icmp6_to_icmp_code(uint8_t type, uint8_t code) {
|
|||
case ICMP6_DST_UNREACH_NOPORT:
|
||||
return ICMP_UNREACH_PORT;
|
||||
|
||||
// Otherwise, we don't understand this ICMPv6 type/code combination. Fall through.
|
||||
// Otherwise, we don't understand this ICMPv6 type/code combination. Fall through.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
40
ipv4.c
40
ipv4.c
|
|
@ -17,11 +17,11 @@
|
|||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include "translate.h"
|
||||
#include "checksum.h"
|
||||
#include "logging.h"
|
||||
#include "debug.h"
|
||||
#include "dump.h"
|
||||
#include "logging.h"
|
||||
#include "translate.h"
|
||||
|
||||
/* function: icmp_packet
|
||||
* translates an icmp packet
|
||||
|
|
@ -36,12 +36,12 @@ int icmp_packet(clat_packet out, clat_packet_index pos, const struct icmphdr *ic
|
|||
const uint8_t *payload;
|
||||
size_t payload_size;
|
||||
|
||||
if(len < sizeof(struct icmphdr)) {
|
||||
if (len < sizeof(struct icmphdr)) {
|
||||
logmsg_dbg(ANDROID_LOG_ERROR, "icmp_packet/(too small)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
payload = (const uint8_t *) (icmp + 1);
|
||||
payload = (const uint8_t *)(icmp + 1);
|
||||
payload_size = len - sizeof(struct icmphdr);
|
||||
|
||||
return icmp_to_icmp6(out, pos, icmp, checksum, payload, payload_size);
|
||||
|
|
@ -55,8 +55,8 @@ int icmp_packet(clat_packet out, clat_packet_index pos, const struct icmphdr *ic
|
|||
* returns: the highest position in the output clat_packet that's filled in
|
||||
*/
|
||||
int ipv4_packet(clat_packet out, clat_packet_index pos, const uint8_t *packet, size_t len) {
|
||||
const struct iphdr *header = (struct iphdr *) packet;
|
||||
struct ip6_hdr *ip6_targ = (struct ip6_hdr *) out[pos].iov_base;
|
||||
const struct iphdr *header = (struct iphdr *)packet;
|
||||
struct ip6_hdr *ip6_targ = (struct ip6_hdr *)out[pos].iov_base;
|
||||
struct ip6_frag *frag_hdr;
|
||||
size_t frag_hdr_len;
|
||||
uint8_t nxthdr;
|
||||
|
|
@ -65,22 +65,22 @@ int ipv4_packet(clat_packet out, clat_packet_index pos, const uint8_t *packet, s
|
|||
uint32_t old_sum, new_sum;
|
||||
int iov_len;
|
||||
|
||||
if(len < sizeof(struct iphdr)) {
|
||||
if (len < sizeof(struct iphdr)) {
|
||||
logmsg_dbg(ANDROID_LOG_ERROR, "ip_packet/too short for an ip header");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(header->ihl < 5) {
|
||||
if (header->ihl < 5) {
|
||||
logmsg_dbg(ANDROID_LOG_ERROR, "ip_packet/ip header length set to less than 5: %x", header->ihl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if((size_t) header->ihl * 4 > len) { // ip header length larger than entire packet
|
||||
if ((size_t)header->ihl * 4 > len) { // ip header length larger than entire packet
|
||||
logmsg_dbg(ANDROID_LOG_ERROR, "ip_packet/ip header length set too large: %x", header->ihl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(header->version != 4) {
|
||||
if (header->version != 4) {
|
||||
logmsg_dbg(ANDROID_LOG_ERROR, "ip_packet/ip header version not 4: %x", header->version);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -90,8 +90,8 @@ int ipv4_packet(clat_packet out, clat_packet_index pos, const uint8_t *packet, s
|
|||
* translate the options.
|
||||
*/
|
||||
|
||||
next_header = packet + header->ihl*4;
|
||||
len_left = len - header->ihl * 4;
|
||||
next_header = packet + header->ihl * 4;
|
||||
len_left = len - header->ihl * 4;
|
||||
|
||||
nxthdr = header->protocol;
|
||||
if (nxthdr == IPPROTO_ICMP) {
|
||||
|
|
@ -115,26 +115,26 @@ int ipv4_packet(clat_packet out, clat_packet_index pos, const uint8_t *packet, s
|
|||
new_sum = ipv6_pseudo_header_checksum(ip6_targ, len_left, nxthdr);
|
||||
|
||||
// If the IPv4 packet is fragmented, add a Fragment header.
|
||||
frag_hdr = (struct ip6_frag *) out[pos + 1].iov_base;
|
||||
frag_hdr_len = maybe_fill_frag_header(frag_hdr, ip6_targ, header);
|
||||
frag_hdr = (struct ip6_frag *)out[pos + 1].iov_base;
|
||||
frag_hdr_len = maybe_fill_frag_header(frag_hdr, ip6_targ, header);
|
||||
out[pos + 1].iov_len = frag_hdr_len;
|
||||
|
||||
if (frag_hdr_len && frag_hdr->ip6f_offlg & IP6F_OFF_MASK) {
|
||||
// Non-first fragment. Copy the rest of the packet as is.
|
||||
iov_len = generic_packet(out, pos + 2, next_header, len_left);
|
||||
} else if (nxthdr == IPPROTO_ICMPV6) {
|
||||
iov_len = icmp_packet(out, pos + 2, (const struct icmphdr *) next_header, new_sum, len_left);
|
||||
iov_len = icmp_packet(out, pos + 2, (const struct icmphdr *)next_header, new_sum, len_left);
|
||||
} else if (nxthdr == IPPROTO_TCP) {
|
||||
iov_len = tcp_packet(out, pos + 2, (const struct tcphdr *) next_header, old_sum, new_sum,
|
||||
len_left);
|
||||
iov_len =
|
||||
tcp_packet(out, pos + 2, (const struct tcphdr *)next_header, old_sum, new_sum, len_left);
|
||||
} else if (nxthdr == IPPROTO_UDP) {
|
||||
iov_len = udp_packet(out, pos + 2, (const struct udphdr *) next_header, old_sum, new_sum,
|
||||
len_left);
|
||||
iov_len =
|
||||
udp_packet(out, pos + 2, (const struct udphdr *)next_header, old_sum, new_sum, len_left);
|
||||
} else if (nxthdr == IPPROTO_GRE) {
|
||||
iov_len = generic_packet(out, pos + 2, next_header, len_left);
|
||||
} else {
|
||||
#if CLAT_DEBUG
|
||||
logmsg_dbg(ANDROID_LOG_ERROR, "ip_packet/unknown protocol: %x",header->protocol);
|
||||
logmsg_dbg(ANDROID_LOG_ERROR, "ip_packet/unknown protocol: %x", header->protocol);
|
||||
logcat_hexdump("ipv4/protocol", packet, len);
|
||||
#endif
|
||||
return 0;
|
||||
|
|
|
|||
38
ipv6.c
38
ipv6.c
|
|
@ -19,12 +19,12 @@
|
|||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "translate.h"
|
||||
#include "checksum.h"
|
||||
#include "logging.h"
|
||||
#include "dump.h"
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "dump.h"
|
||||
#include "logging.h"
|
||||
#include "translate.h"
|
||||
|
||||
/* function: icmp6_packet
|
||||
* takes an icmp6 packet and sets it up for translation
|
||||
|
|
@ -39,12 +39,12 @@ int icmp6_packet(clat_packet out, clat_packet_index pos, const struct icmp6_hdr
|
|||
const uint8_t *payload;
|
||||
size_t payload_size;
|
||||
|
||||
if(len < sizeof(struct icmp6_hdr)) {
|
||||
if (len < sizeof(struct icmp6_hdr)) {
|
||||
logmsg_dbg(ANDROID_LOG_ERROR, "icmp6_packet/(too small)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
payload = (const uint8_t *) (icmp6 + 1);
|
||||
payload = (const uint8_t *)(icmp6 + 1);
|
||||
payload_size = len - sizeof(struct icmp6_hdr);
|
||||
|
||||
return icmp6_to_icmp(out, pos, icmp6, payload, payload_size);
|
||||
|
|
@ -76,8 +76,8 @@ void log_bad_address(const char *fmt, const struct in6_addr *src, const struct i
|
|||
* returns: the highest position in the output clat_packet that's filled in
|
||||
*/
|
||||
int ipv6_packet(clat_packet out, clat_packet_index pos, const uint8_t *packet, size_t len) {
|
||||
const struct ip6_hdr *ip6 = (struct ip6_hdr *) packet;
|
||||
struct iphdr *ip_targ = (struct iphdr *) out[pos].iov_base;
|
||||
const struct ip6_hdr *ip6 = (struct ip6_hdr *)packet;
|
||||
struct iphdr *ip_targ = (struct iphdr *)out[pos].iov_base;
|
||||
struct ip6_frag *frag_hdr = NULL;
|
||||
uint8_t protocol;
|
||||
const uint8_t *next_header;
|
||||
|
|
@ -85,14 +85,14 @@ int ipv6_packet(clat_packet out, clat_packet_index pos, const uint8_t *packet, s
|
|||
uint32_t old_sum, new_sum;
|
||||
int iov_len;
|
||||
|
||||
if(len < sizeof(struct ip6_hdr)) {
|
||||
if (len < sizeof(struct ip6_hdr)) {
|
||||
logmsg_dbg(ANDROID_LOG_ERROR, "ipv6_packet/too short for an ip6 header: %d", len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
|
||||
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
|
||||
log_bad_address("ipv6_packet/multicast %s->%s", &ip6->ip6_src, &ip6->ip6_dst);
|
||||
return 0; // silently ignore
|
||||
return 0; // silently ignore
|
||||
}
|
||||
|
||||
// If the packet is not from the plat subnet to the local subnet, or vice versa, drop it, unless
|
||||
|
|
@ -111,7 +111,7 @@ int ipv6_packet(clat_packet out, clat_packet_index pos, const uint8_t *packet, s
|
|||
}
|
||||
|
||||
next_header = packet + sizeof(struct ip6_hdr);
|
||||
len_left = len - sizeof(struct ip6_hdr);
|
||||
len_left = len - sizeof(struct ip6_hdr);
|
||||
|
||||
protocol = ip6->ip6_nxt;
|
||||
|
||||
|
|
@ -125,7 +125,7 @@ int ipv6_packet(clat_packet out, clat_packet_index pos, const uint8_t *packet, s
|
|||
// If there's a Fragment header, parse it and decide what the next header is.
|
||||
// Do this before calculating the pseudo-header checksum because it updates the next header value.
|
||||
if (protocol == IPPROTO_FRAGMENT) {
|
||||
frag_hdr = (struct ip6_frag *) next_header;
|
||||
frag_hdr = (struct ip6_frag *)next_header;
|
||||
if (len_left < sizeof(*frag_hdr)) {
|
||||
logmsg_dbg(ANDROID_LOG_ERROR, "ipv6_packet/too short for fragment header: %d", len);
|
||||
return 0;
|
||||
|
|
@ -139,7 +139,7 @@ int ipv6_packet(clat_packet out, clat_packet_index pos, const uint8_t *packet, s
|
|||
|
||||
// ICMP and ICMPv6 have different protocol numbers.
|
||||
if (protocol == IPPROTO_ICMPV6) {
|
||||
protocol = IPPROTO_ICMP;
|
||||
protocol = IPPROTO_ICMP;
|
||||
ip_targ->protocol = IPPROTO_ICMP;
|
||||
}
|
||||
|
||||
|
|
@ -155,13 +155,13 @@ int ipv6_packet(clat_packet out, clat_packet_index pos, const uint8_t *packet, s
|
|||
if (frag_hdr && (frag_hdr->ip6f_offlg & IP6F_OFF_MASK)) {
|
||||
iov_len = generic_packet(out, pos + 2, next_header, len_left);
|
||||
} else if (protocol == IPPROTO_ICMP) {
|
||||
iov_len = icmp6_packet(out, pos + 2, (const struct icmp6_hdr *) next_header, len_left);
|
||||
iov_len = icmp6_packet(out, pos + 2, (const struct icmp6_hdr *)next_header, len_left);
|
||||
} else if (protocol == IPPROTO_TCP) {
|
||||
iov_len = tcp_packet(out, pos + 2, (const struct tcphdr *) next_header, old_sum, new_sum,
|
||||
len_left);
|
||||
iov_len =
|
||||
tcp_packet(out, pos + 2, (const struct tcphdr *)next_header, old_sum, new_sum, len_left);
|
||||
} else if (protocol == IPPROTO_UDP) {
|
||||
iov_len = udp_packet(out, pos + 2, (const struct udphdr *) next_header, old_sum, new_sum,
|
||||
len_left);
|
||||
iov_len =
|
||||
udp_packet(out, pos + 2, (const struct udphdr *)next_header, old_sum, new_sum, len_left);
|
||||
} else if (protocol == IPPROTO_GRE) {
|
||||
iov_len = generic_packet(out, pos + 2, next_header, len_left);
|
||||
} else {
|
||||
|
|
@ -174,6 +174,6 @@ int ipv6_packet(clat_packet out, clat_packet_index pos, const uint8_t *packet, s
|
|||
|
||||
// Set the length and calculate the checksum.
|
||||
ip_targ->tot_len = htons(ntohs(ip_targ->tot_len) + packet_length(out, pos));
|
||||
ip_targ->check = ip_checksum(ip_targ, sizeof(struct iphdr));
|
||||
ip_targ->check = ip_checksum(ip_targ, sizeof(struct iphdr));
|
||||
return iov_len;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@
|
|||
* logging.c - print a log message
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <android/log.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "logging.h"
|
||||
#include "debug.h"
|
||||
#include "logging.h"
|
||||
|
||||
/* function: logmsg
|
||||
* prints a log message to android's log buffer
|
||||
|
|
|
|||
14
mtu.c
14
mtu.c
|
|
@ -16,12 +16,12 @@
|
|||
* mtu.c - get interface mtu
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "mtu.h"
|
||||
|
||||
|
|
@ -34,12 +34,12 @@ int getifmtu(const char *ifname) {
|
|||
struct ifreq if_mtu;
|
||||
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(fd < 0) {
|
||||
if (fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
strncpy(if_mtu.ifr_name, ifname, IFNAMSIZ);
|
||||
if_mtu.ifr_name[IFNAMSIZ - 1] = '\0';
|
||||
if(ioctl(fd, SIOCGIFMTU, &if_mtu) < 0) {
|
||||
if (ioctl(fd, SIOCGIFMTU, &if_mtu) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return if_mtu.ifr_mtu;
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@
|
|||
*
|
||||
* netlink_callbacks.c - generic callbacks for netlink responses
|
||||
*/
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <netlink/handlers.h>
|
||||
|
|
@ -29,7 +29,7 @@
|
|||
*/
|
||||
static int ack_handler(__attribute__((unused)) struct nl_msg *msg, void *data) {
|
||||
int *retval = data;
|
||||
*retval = 0;
|
||||
*retval = 0;
|
||||
return NL_OK;
|
||||
}
|
||||
|
||||
|
|
@ -39,26 +39,26 @@ static int ack_handler(__attribute__((unused)) struct nl_msg *msg, void *data) {
|
|||
* err - netlink error message
|
||||
* arg - pointer to an int, stores the error code
|
||||
*/
|
||||
static int error_handler(__attribute__((unused)) struct sockaddr_nl *nla,
|
||||
struct nlmsgerr *err, void *arg) {
|
||||
static int error_handler(__attribute__((unused)) struct sockaddr_nl *nla, struct nlmsgerr *err,
|
||||
void *arg) {
|
||||
int *retval = arg;
|
||||
if(err->error < 0) {
|
||||
if (err->error < 0) {
|
||||
*retval = err->error;
|
||||
} else {
|
||||
*retval = 0; // NLMSG_ERROR used as reply type on no error
|
||||
*retval = 0; // NLMSG_ERROR used as reply type on no error
|
||||
}
|
||||
return NL_OK;
|
||||
}
|
||||
|
||||
/* function: alloc_ack_callbacks
|
||||
* allocates a set of netlink callbacks. returns NULL on failure. callbacks will modify retval with <0 meaning failure
|
||||
* retval - shared state between caller and callback functions
|
||||
* allocates a set of netlink callbacks. returns NULL on failure. callbacks will modify retval
|
||||
* with <0 meaning failure retval - shared state between caller and callback functions
|
||||
*/
|
||||
struct nl_cb *alloc_ack_callbacks(int *retval) {
|
||||
struct nl_cb *callbacks;
|
||||
|
||||
callbacks = nl_cb_alloc(NL_CB_DEFAULT);
|
||||
if(!callbacks) {
|
||||
if (!callbacks) {
|
||||
return NULL;
|
||||
}
|
||||
nl_cb_set(callbacks, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, retval);
|
||||
|
|
|
|||
|
|
@ -16,29 +16,29 @@
|
|||
* netlink_msg.c - send an ifaddrmsg/ifinfomsg/rtmsg via netlink
|
||||
*/
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <netlink-private/object-api.h>
|
||||
#include <netlink-private/types.h>
|
||||
#include <netlink/socket.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/msg.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/socket.h>
|
||||
|
||||
#include "netlink_msg.h"
|
||||
#include "netlink_callbacks.h"
|
||||
#include "netlink_msg.h"
|
||||
|
||||
/* function: family_size
|
||||
* returns the size of the address structure for the given family, or 0 on error
|
||||
* family - AF_INET or AF_INET6
|
||||
*/
|
||||
size_t inet_family_size(int family) {
|
||||
if(family == AF_INET) {
|
||||
if (family == AF_INET) {
|
||||
return sizeof(struct in_addr);
|
||||
} else if(family == AF_INET6) {
|
||||
} else if (family == AF_INET6) {
|
||||
return sizeof(struct in6_addr);
|
||||
} else {
|
||||
return 0;
|
||||
|
|
@ -52,11 +52,12 @@ size_t inet_family_size(int family) {
|
|||
* payload_struct - pointer to a struct to add to netlink message
|
||||
* payload_len - bytelength of structure
|
||||
*/
|
||||
struct nl_msg *nlmsg_alloc_generic(uint16_t type, uint16_t flags, void *payload_struct, size_t payload_len) {
|
||||
struct nl_msg *nlmsg_alloc_generic(uint16_t type, uint16_t flags, void *payload_struct,
|
||||
size_t payload_len) {
|
||||
struct nl_msg *msg;
|
||||
|
||||
msg = nlmsg_alloc();
|
||||
if(!msg) {
|
||||
if (!msg) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -65,9 +66,9 @@ struct nl_msg *nlmsg_alloc_generic(uint16_t type, uint16_t flags, void *payload_
|
|||
return NULL;
|
||||
}
|
||||
|
||||
msg->nm_nlh->nlmsg_len = NLMSG_LENGTH(payload_len);
|
||||
msg->nm_nlh->nlmsg_len = NLMSG_LENGTH(payload_len);
|
||||
msg->nm_nlh->nlmsg_flags = flags;
|
||||
msg->nm_nlh->nlmsg_type = type;
|
||||
msg->nm_nlh->nlmsg_type = type;
|
||||
|
||||
memcpy(nlmsg_data(msg->nm_nlh), payload_struct, payload_len);
|
||||
|
||||
|
|
@ -116,7 +117,7 @@ int netlink_set_kernel_only(struct nl_sock *nl_sk) {
|
|||
}
|
||||
|
||||
int sockfd = nl_socket_get_fd(nl_sk);
|
||||
return connect(sockfd, (struct sockaddr *) &addr, sizeof(addr));
|
||||
return connect(sockfd, (struct sockaddr *)&addr, sizeof(addr));
|
||||
}
|
||||
|
||||
/* function: send_netlink_msg
|
||||
|
|
@ -128,23 +129,18 @@ void send_netlink_msg(struct nl_msg *msg, struct nl_cb *callbacks) {
|
|||
struct nl_sock *nl_sk;
|
||||
|
||||
nl_sk = nl_socket_alloc();
|
||||
if(!nl_sk)
|
||||
goto cleanup;
|
||||
if (!nl_sk) goto cleanup;
|
||||
|
||||
if(nl_connect(nl_sk, NETLINK_ROUTE) != 0)
|
||||
goto cleanup;
|
||||
if (nl_connect(nl_sk, NETLINK_ROUTE) != 0) goto cleanup;
|
||||
|
||||
if(nl_send_auto_complete(nl_sk, msg) < 0)
|
||||
goto cleanup;
|
||||
if (nl_send_auto_complete(nl_sk, msg) < 0) goto cleanup;
|
||||
|
||||
if(netlink_set_kernel_only(nl_sk) < 0)
|
||||
goto cleanup;
|
||||
if (netlink_set_kernel_only(nl_sk) < 0) goto cleanup;
|
||||
|
||||
nl_recvmsgs(nl_sk, callbacks);
|
||||
|
||||
cleanup:
|
||||
if(nl_sk)
|
||||
nl_socket_free(nl_sk);
|
||||
if (nl_sk) nl_socket_free(nl_sk);
|
||||
}
|
||||
|
||||
/* function: send_ifaddrmsg
|
||||
|
|
@ -158,8 +154,7 @@ void send_ifaddrmsg(uint16_t type, uint16_t flags, struct ifaddrmsg *ifa, struct
|
|||
struct nl_msg *msg = NULL;
|
||||
|
||||
msg = nlmsg_alloc_ifaddr(type, flags, ifa);
|
||||
if(!msg)
|
||||
return;
|
||||
if (!msg) return;
|
||||
|
||||
send_netlink_msg(msg, callbacks);
|
||||
|
||||
|
|
@ -172,10 +167,10 @@ void send_ifaddrmsg(uint16_t type, uint16_t flags, struct ifaddrmsg *ifa, struct
|
|||
*/
|
||||
int netlink_sendrecv(struct nl_msg *msg) {
|
||||
struct nl_cb *callbacks = NULL;
|
||||
int retval = -EIO;
|
||||
int retval = -EIO;
|
||||
|
||||
callbacks = alloc_ack_callbacks(&retval);
|
||||
if(!callbacks) {
|
||||
if (!callbacks) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
|
|
|||
46
ring.c
46
ring.c
|
|
@ -16,13 +16,13 @@
|
|||
* ring.c - packet ring buffer functions
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/mman.h>
|
||||
#include <errno.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "logging.h"
|
||||
#include "ring.h"
|
||||
|
|
@ -37,26 +37,26 @@ int ring_create(struct tun_data *tunnel) {
|
|||
}
|
||||
|
||||
int ver = TPACKET_V2;
|
||||
if (setsockopt(packetsock, SOL_PACKET, PACKET_VERSION, (void *) &ver, sizeof(ver))) {
|
||||
if (setsockopt(packetsock, SOL_PACKET, PACKET_VERSION, (void *)&ver, sizeof(ver))) {
|
||||
logmsg(ANDROID_LOG_FATAL, "setsockopt(PACKET_VERSION, %d) failed: %s", ver, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
int on = 1;
|
||||
if (setsockopt(packetsock, SOL_PACKET, PACKET_LOSS, (void *) &on, sizeof(on))) {
|
||||
if (setsockopt(packetsock, SOL_PACKET, PACKET_LOSS, (void *)&on, sizeof(on))) {
|
||||
logmsg(ANDROID_LOG_WARN, "PACKET_LOSS failed: %s", strerror(errno));
|
||||
}
|
||||
|
||||
struct packet_ring *ring = &tunnel->ring;
|
||||
ring->numblocks = TP_NUM_BLOCKS;
|
||||
ring->numblocks = TP_NUM_BLOCKS;
|
||||
|
||||
int total_frames = TP_FRAMES * ring->numblocks;
|
||||
|
||||
struct tpacket_req req = {
|
||||
.tp_frame_size = TP_FRAME_SIZE, // Frame size.
|
||||
.tp_block_size = TP_BLOCK_SIZE, // Frames per block.
|
||||
.tp_block_nr = ring->numblocks, // Number of blocks.
|
||||
.tp_frame_nr = total_frames, // Total frames.
|
||||
.tp_frame_size = TP_FRAME_SIZE, // Frame size.
|
||||
.tp_block_size = TP_BLOCK_SIZE, // Frames per block.
|
||||
.tp_block_nr = ring->numblocks, // Number of blocks.
|
||||
.tp_frame_nr = total_frames, // Total frames.
|
||||
};
|
||||
|
||||
if (setsockopt(packetsock, SOL_PACKET, PACKET_RX_RING, &req, sizeof(req)) < 0) {
|
||||
|
|
@ -65,20 +65,20 @@ int ring_create(struct tun_data *tunnel) {
|
|||
}
|
||||
|
||||
size_t buflen = TP_BLOCK_SIZE * ring->numblocks;
|
||||
ring->base = mmap(NULL, buflen, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED|MAP_POPULATE,
|
||||
ring->base = mmap(NULL, buflen, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED | MAP_POPULATE,
|
||||
packetsock, 0);
|
||||
if (ring->base == MAP_FAILED) {
|
||||
logmsg(ANDROID_LOG_FATAL, "mmap %lu failed: %s", buflen, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
ring->block = 0;
|
||||
ring->slot = 0;
|
||||
ring->block = 0;
|
||||
ring->slot = 0;
|
||||
ring->numslots = TP_BLOCK_SIZE / TP_FRAME_SIZE;
|
||||
ring->next = (struct tpacket2_hdr *) ring->base;
|
||||
ring->next = (struct tpacket2_hdr *)ring->base;
|
||||
|
||||
logmsg(ANDROID_LOG_INFO, "Using ring buffer with %d frames (%d bytes) at %p",
|
||||
total_frames, buflen, ring->base);
|
||||
logmsg(ANDROID_LOG_INFO, "Using ring buffer with %d frames (%d bytes) at %p", total_frames,
|
||||
buflen, ring->base);
|
||||
|
||||
return packetsock;
|
||||
}
|
||||
|
|
@ -87,8 +87,8 @@ int ring_create(struct tun_data *tunnel) {
|
|||
* advances to the next position in the packet ring
|
||||
* ring - packet ring buffer
|
||||
*/
|
||||
static struct tpacket2_hdr* ring_advance(struct packet_ring *ring) {
|
||||
uint8_t *next = (uint8_t *) ring->next;
|
||||
static struct tpacket2_hdr *ring_advance(struct packet_ring *ring) {
|
||||
uint8_t *next = (uint8_t *)ring->next;
|
||||
|
||||
ring->slot++;
|
||||
next += TP_FRAME_SIZE;
|
||||
|
|
@ -101,11 +101,11 @@ static struct tpacket2_hdr* ring_advance(struct packet_ring *ring) {
|
|||
next += TP_FRAME_GAP;
|
||||
} else {
|
||||
ring->block = 0;
|
||||
next = (uint8_t *) ring->base;
|
||||
next = (uint8_t *)ring->base;
|
||||
}
|
||||
}
|
||||
|
||||
ring->next = (struct tpacket2_hdr *) next;
|
||||
ring->next = (struct tpacket2_hdr *)next;
|
||||
return ring->next;
|
||||
}
|
||||
|
||||
|
|
@ -118,9 +118,9 @@ static struct tpacket2_hdr* ring_advance(struct packet_ring *ring) {
|
|||
void ring_read(struct packet_ring *ring, int write_fd, int to_ipv6) {
|
||||
struct tpacket2_hdr *tp = ring->next;
|
||||
if (tp->tp_status & TP_STATUS_USER) {
|
||||
uint8_t *packet = ((uint8_t *) tp) + tp->tp_net;
|
||||
uint8_t *packet = ((uint8_t *)tp) + tp->tp_net;
|
||||
translate_packet(write_fd, to_ipv6, packet, tp->tp_len);
|
||||
tp->tp_status = TP_STATUS_KERNEL;
|
||||
tp = ring_advance(ring);
|
||||
tp = ring_advance(ring);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue