static int should_filter_query(ns_msg msg, struct in_addr dns_addr) { ns_rr rr; int rrnum, rrmax; void *r; // TODO cache result for each dns server int dns_is_chn = chnroute_file && (dns_servers_len > 1) && test_ip_in_list(dns_addr, &chnroute_list); rrmax = ns_msg_count(msg, ns_s_an); if (rrmax == 0) return -1; for (rrnum = 0; rrnum < rrmax; rrnum++) { if (ns_parserr(&msg, ns_s_an, rrnum, &rr)) { ERR("ns_parserr"); return 0; } u_int type; const u_char *rd; type = ns_rr_type(rr); rd = ns_rr_rdata(rr); if (type == ns_t_a) { if (verbose) printf("%s, ", inet_ntoa(*(struct in_addr *)rd)); r = bsearch(rd, ip_list.ips, ip_list.entries, sizeof(struct in_addr), cmp_in_addr); if (r) return 1; if (chnroute_file && dns_is_chn) { // filter DNS result from chn dns if result is outside chn if (!test_ip_in_list(*(struct in_addr *)rd, &chnroute_list)) return 1; } } } return 0; }
static int should_filter_query(ns_msg msg, struct in_addr dns_addr) { ns_rr rr; int rrnum, rrmax; void *r; // TODO cache result for each dns server int dns_is_chn = 0; int dns_is_foreign = 0; if (chnroute_file && (dns_servers_len > 1)) { dns_is_chn = test_ip_in_list(dns_addr, &chnroute_list); dns_is_foreign = !dns_is_chn; } rrmax = ns_msg_count(msg, ns_s_an); if (rrmax == 0) { if (compression) { // Wait for foreign dns if (dns_is_chn) { return 1; } else { return 0; } } return -1; } for (rrnum = 0; rrnum < rrmax; rrnum++) { if (ns_parserr(&msg, ns_s_an, rrnum, &rr)) { ERR("ns_parserr"); return 0; } u_int type; const u_char *rd; type = ns_rr_type(rr); rd = ns_rr_rdata(rr); if (type == ns_t_a) { if (verbose) printf("%s, ", inet_ntoa(*(struct in_addr *)rd)); if (!compression) { r = bsearch(rd, ip_list.ips, ip_list.entries, sizeof(struct in_addr), cmp_in_addr); if (r) { return 1; } } if (test_ip_in_list(*(struct in_addr *)rd, &chnroute_list)) { // result is chn if (dns_is_foreign) { if (bidirectional) { // filter DNS result from foreign dns if result is inside chn return 1; } } } else { // result is foreign if (dns_is_chn) { // filter DNS result from chn dns if result is outside chn return 1; } } } else if (type == ns_t_aaaa || type == ns_t_ptr) { // if we've got an IPv6 result or a PTR result, pass return 0; } } if (rrmax == 1) { if (compression) { return 0; } else { return -1; } } return 0; }
static int resolve_dns_servers() { struct addrinfo hints; struct addrinfo *addr_ip; char* token; int r; int i = 0; char *pch = strchr(dns_servers, ','); has_chn_dns = 0; int has_foreign_dns = 0; dns_servers_len = 1; if (compression) { if (!chnroute_file) { VERR("Chnroutes are necessary when using DNS compression pointer mutation\n"); return -1; } } while (pch != NULL) { dns_servers_len++; pch = strchr(pch + 1, ','); } dns_server_addrs = calloc(dns_servers_len, sizeof(id_addr_t)); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ token = strtok(dns_servers, ","); while (token) { char *port; memset(global_buf, 0, BUF_SIZE); strncpy(global_buf, token, BUF_SIZE - 1); port = (strrchr(global_buf, ':')); if (port) { *port = '\0'; port++; } else { port = "53"; } if (0 != (r = getaddrinfo(global_buf, port, &hints, &addr_ip))) { VERR("%s:%s\n", gai_strerror(r), token); return -1; } if (compression) { if (test_ip_in_list(((struct sockaddr_in *)addr_ip->ai_addr)->sin_addr, &chnroute_list)) { dns_server_addrs[has_chn_dns].addr = addr_ip->ai_addr; dns_server_addrs[has_chn_dns].addrlen = addr_ip->ai_addrlen; has_chn_dns++; } else { has_foreign_dns++; dns_server_addrs[dns_servers_len - has_foreign_dns].addr = addr_ip->ai_addr; dns_server_addrs[dns_servers_len - has_foreign_dns].addrlen = addr_ip->ai_addrlen; } token = strtok(0, ","); } else { dns_server_addrs[i].addr = addr_ip->ai_addr; dns_server_addrs[i].addrlen = addr_ip->ai_addrlen; i++; token = strtok(0, ","); if (chnroute_file) { if (test_ip_in_list(((struct sockaddr_in *)addr_ip->ai_addr)->sin_addr, &chnroute_list)) { has_chn_dns = 1; } else { has_foreign_dns = 1; } } } } if (chnroute_file) { if (!(has_chn_dns && has_foreign_dns)) { if (compression) { VERR("You should have at least one Chinese DNS and one foreign DNS when " "using DNS compression pointer mutation\n"); return -1; } else { VERR("You should have at least one Chinese DNS and one foreign DNS when " "chnroutes is enabled\n"); return 0; } } } return 0; }