Commit b3e3cb07 authored by Max Lv's avatar Max Lv

add dnsgw

parent 9517d1f3
...@@ -114,6 +114,7 @@ struct { ...@@ -114,6 +114,7 @@ struct {
int tun_fd; int tun_fd;
int tun_mtu; int tun_mtu;
char *pid; char *pid;
char *dnsgw;
#else #else
char *tundev; char *tundev;
#endif #endif
...@@ -207,6 +208,11 @@ LinkedList1 tcp_clients; ...@@ -207,6 +208,11 @@ LinkedList1 tcp_clients;
// number of clients // number of clients
int num_clients; int num_clients;
#ifdef ANDROID
// IP address of dnsgw
BIPAddr dnsgw;
#endif
static void terminate (void); static void terminate (void);
static void print_help (const char *name); static void print_help (const char *name);
static void print_version (void); static void print_version (void);
...@@ -218,6 +224,9 @@ static void lwip_init_job_hadler (void *unused); ...@@ -218,6 +224,9 @@ static void lwip_init_job_hadler (void *unused);
static void tcp_timer_handler (void *unused); static void tcp_timer_handler (void *unused);
static void device_error_handler (void *unused); static void device_error_handler (void *unused);
static void device_read_handler_send (void *unused, uint8_t *data, int data_len); static void device_read_handler_send (void *unused, uint8_t *data, int data_len);
#ifdef ANDROID
static int process_device_dns_packet (uint8_t *data, int data_len);
#endif
static int process_device_udp_packet (uint8_t *data, int data_len); static int process_device_udp_packet (uint8_t *data, int data_len);
static err_t netif_init_func (struct netif *netif); static err_t netif_init_func (struct netif *netif);
static err_t netif_output_func (struct netif *netif, struct pbuf *p, ip_addr_t *ipaddr); static err_t netif_output_func (struct netif *netif, struct pbuf *p, ip_addr_t *ipaddr);
...@@ -563,6 +572,7 @@ void print_help (const char *name) ...@@ -563,6 +572,7 @@ void print_help (const char *name)
#ifdef ANDROID #ifdef ANDROID
" [--tunfd <fd>]\n" " [--tunfd <fd>]\n"
" [--tunmtu <mtu>]\n" " [--tunmtu <mtu>]\n"
" [--dnsgw <dns_gateway_address>]\n"
" [--pid <pid_file>]\n" " [--pid <pid_file>]\n"
#else #else
" [--tundev <name>]\n" " [--tundev <name>]\n"
...@@ -725,6 +735,14 @@ int parse_arguments (int argc, char *argv[]) ...@@ -725,6 +735,14 @@ int parse_arguments (int argc, char *argv[])
} }
i++; i++;
} }
else if (!strcmp(arg, "--dnsgw")) {
if (1 >= argc - i) {
fprintf(stderr, "%s: requires an argument\n", arg);
return 0;
}
options.dnsgw = argv[i + 1];
i++;
}
else if (!strcmp(arg, "--pid")) { else if (!strcmp(arg, "--pid")) {
if (1 >= argc - i) { if (1 >= argc - i) {
fprintf(stderr, "%s: requires an argument\n", arg); fprintf(stderr, "%s: requires an argument\n", arg);
...@@ -878,6 +896,20 @@ int parse_arguments (int argc, char *argv[]) ...@@ -878,6 +896,20 @@ int parse_arguments (int argc, char *argv[])
int process_arguments (void) int process_arguments (void)
{ {
ASSERT(!password_file_contents) ASSERT(!password_file_contents)
#ifdef ANDROID
// resolve dnsgw ipaddr
if (options.dnsgw) {
if (!BIPAddr_Resolve(&dnsgw, options.dnsgw, 0)) {
BLog(BLOG_ERROR, "dnsgw ipaddr: BIPAddr_Resolve failed");
return 0;
}
if (dnsgw.type != BADDR_TYPE_IPV4) {
BLog(BLOG_ERROR, "dnsgw ipaddr: must be an IPv4 address");
return 0;
}
}
#endif
// resolve netif ipaddr // resolve netif ipaddr
if (!BIPAddr_Resolve(&netif_ipaddr, options.netif_ipaddr, 0)) { if (!BIPAddr_Resolve(&netif_ipaddr, options.netif_ipaddr, 0)) {
...@@ -1103,6 +1135,13 @@ void device_read_handler_send (void *unused, uint8_t *data, int data_len) ...@@ -1103,6 +1135,13 @@ void device_read_handler_send (void *unused, uint8_t *data, int data_len)
// accept packet // accept packet
PacketPassInterface_Done(&device_read_interface); PacketPassInterface_Done(&device_read_interface);
#ifdef ANDROID
// process DNS directly
if (process_device_dns_packet(data, data_len)) {
return;
}
#endif
// process UDP directly // process UDP directly
if (process_device_udp_packet(data, data_len)) { if (process_device_udp_packet(data, data_len)) {
...@@ -1130,6 +1169,101 @@ void device_read_handler_send (void *unused, uint8_t *data, int data_len) ...@@ -1130,6 +1169,101 @@ void device_read_handler_send (void *unused, uint8_t *data, int data_len)
} }
} }
#ifdef ANDROID
int process_device_dns_packet (uint8_t *data, int data_len)
{
ASSERT(data_len >= 0)
// do nothing if we don't have dnsgw
if (!options.dnsgw) {
goto fail;
}
BAddr local_addr;
BAddr remote_addr;
int is_dns;
int packet_length = 0;
uint8_t ip_version = 0;
if (data_len > 0) {
ip_version = (data[0] >> 4);
}
switch (ip_version) {
case 4: {
// ignore non-UDP packets
if (data_len < sizeof(struct ipv4_header) || data[offsetof(struct ipv4_header, protocol)] != IPV4_PROTOCOL_UDP) {
goto fail;
}
// parse IPv4 header
struct ipv4_header ipv4_header;
if (!ipv4_check(data, data_len, &ipv4_header, &data, &data_len)) {
goto fail;
}
// parse UDP
struct udp_header udp_header;
if (!udp_check(data, data_len, &udp_header, &data, &data_len)) {
goto fail;
}
// verify UDP checksum
uint16_t checksum_in_packet = udp_header.checksum;
udp_header.checksum = 0;
uint16_t checksum_computed = udp_checksum(&udp_header, data, data_len, ipv4_header.source_address, ipv4_header.destination_address);
if (checksum_in_packet != checksum_computed) {
goto fail;
}
BLog(BLOG_INFO, "UDP: from device %d bytes", data_len);
// to port 53 is considered a DNS packet
is_dns = udp_header.dest_port == hton16(53);
// if not DNS packet, just bypass it.
if (!is_dns) {
goto fail;
}
// build IP header
ipv4_header.destination_address = dnsgw.ipv4;
ipv4_header.checksum = hton16(0);
ipv4_header.checksum = ipv4_checksum(&ipv4_header, NULL, 0);
// build UDP header
udp_header.checksum = hton16(0);
udp_header.checksum = udp_checksum(&udp_header, data, data_len,
ipv4_header.source_address, ipv4_header.destination_address);
// write packet
memcpy(device_write_buf, &ipv4_header, sizeof(ipv4_header));
memcpy(device_write_buf + sizeof(ipv4_header), &udp_header, sizeof(udp_header));
memcpy(device_write_buf + sizeof(ipv4_header) + sizeof(udp_header), data, data_len);
packet_length = sizeof(ipv4_header) + sizeof(udp_header) + data_len;
} break;
case 6: {
// TODO: support IPv6 DNS Gateway
goto fail;
} break;
default: {
goto fail;
} break;
}
// submit packet
BTap_Send(&device, device_write_buf, packet_length);
return 1;
fail:
return 0;
}
#endif
int process_device_udp_packet (uint8_t *data, int data_len) int process_device_udp_packet (uint8_t *data, int data_len)
{ {
ASSERT(data_len >= 0) ASSERT(data_len >= 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment