update 2023-11-10 23:36:09
This commit is contained in:
parent
29eaa696f7
commit
8dc89bb6e2
|
@ -14,7 +14,7 @@ _Noreturn static void check_cache() {
|
||||||
while (true) {
|
while (true) {
|
||||||
pthread_rwlock_wrlock(&cacheLock);
|
pthread_rwlock_wrlock(&cacheLock);
|
||||||
|
|
||||||
time_t now = time(NULL);
|
const time_t now = time(NULL);
|
||||||
struct cache *cur, *tmp;
|
struct cache *cur, *tmp;
|
||||||
|
|
||||||
HASH_ITER(hh, not_http_dst_cache, cur, tmp) {
|
HASH_ITER(hh, not_http_dst_cache, cur, tmp) {
|
||||||
|
@ -39,7 +39,7 @@ void init_not_http_cache() {
|
||||||
syslog(LOG_INFO, "Cache lock initialized");
|
syslog(LOG_INFO, "Cache lock initialized");
|
||||||
|
|
||||||
pthread_t cleanup_thread;
|
pthread_t cleanup_thread;
|
||||||
__auto_type ret = pthread_create(&cleanup_thread, NULL, (void *(*)(void *)) check_cache, NULL);
|
const __auto_type ret = pthread_create(&cleanup_thread, NULL, check_cache, NULL);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
syslog(LOG_ERR, "Failed to create cleanup thread: %d", ret);
|
syslog(LOG_ERR, "Failed to create cleanup thread: %d", ret);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
// handle print --version and --help
|
// handle print --version and --help
|
||||||
void try_print_info(int argc, char *argv[]) {
|
void try_print_info(const int argc, char *argv[]) {
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ struct ua2f_config config = {
|
||||||
};
|
};
|
||||||
|
|
||||||
void load_config() {
|
void load_config() {
|
||||||
__auto_type ctx = uci_alloc_context();
|
const __auto_type ctx = uci_alloc_context();
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
syslog(LOG_ERR, "Failed to allocate uci context");
|
syslog(LOG_ERR, "Failed to allocate uci context");
|
||||||
return;
|
return;
|
||||||
|
@ -22,12 +22,12 @@ void load_config() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// find ua2f.main.custom_ua
|
// find ua2f.main.custom_ua
|
||||||
__auto_type section = uci_lookup_section(ctx, package, "main");
|
const __auto_type section = uci_lookup_section(ctx, package, "main");
|
||||||
if (!section) {
|
if (!section) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
__auto_type custom_ua = uci_lookup_option_string(ctx, section, "custom_ua");
|
const __auto_type custom_ua = uci_lookup_option_string(ctx, section, "custom_ua");
|
||||||
if (!custom_ua) {
|
if (!custom_ua) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include <libnetfilter_queue/libnetfilter_queue_ipv6.h>
|
#include <libnetfilter_queue/libnetfilter_queue_ipv6.h>
|
||||||
|
|
||||||
#define MAX_USER_AGENT_LENGTH (0xffff + (MNL_SOCKET_BUFFER_SIZE / 2))
|
#define MAX_USER_AGENT_LENGTH (0xffff + (MNL_SOCKET_BUFFER_SIZE / 2))
|
||||||
static char *replacement_user_agent_string = NULL;
|
static char* replacement_user_agent_string = NULL;
|
||||||
|
|
||||||
#define USER_AGENT_MATCH "\r\nUser-Agent:"
|
#define USER_AGENT_MATCH "\r\nUser-Agent:"
|
||||||
#define USER_AGENT_MATCH_LENGTH 13
|
#define USER_AGENT_MATCH_LENGTH 13
|
||||||
|
@ -31,7 +31,8 @@ void init_handler() {
|
||||||
memset(replacement_user_agent_string, ' ', MAX_USER_AGENT_LENGTH);
|
memset(replacement_user_agent_string, ' ', MAX_USER_AGENT_LENGTH);
|
||||||
strncpy(replacement_user_agent_string, config.custom_ua, strlen(config.custom_ua));
|
strncpy(replacement_user_agent_string, config.custom_ua, strlen(config.custom_ua));
|
||||||
syslog(LOG_INFO, "Using config user agent string: %s", replacement_user_agent_string);
|
syslog(LOG_INFO, "Using config user agent string: %s", replacement_user_agent_string);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
#ifdef UA2F_CUSTOM_UA
|
#ifdef UA2F_CUSTOM_UA
|
||||||
memset(replacement_user_agent_string, ' ', MAX_USER_AGENT_LENGTH);
|
memset(replacement_user_agent_string, ' ', MAX_USER_AGENT_LENGTH);
|
||||||
strncpy(replacement_user_agent_string, UA2F_CUSTOM_UA, strlen(UA2F_CUSTOM_UA));
|
strncpy(replacement_user_agent_string, UA2F_CUSTOM_UA, strlen(UA2F_CUSTOM_UA));
|
||||||
|
@ -46,15 +47,16 @@ void init_handler() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// should free the ret value
|
// should free the ret value
|
||||||
static char *ip_to_str(ip_address_t *ip, uint16_t port, int ip_version) {
|
static char* ip_to_str(const ip_address_t* ip, const uint16_t port, const int ip_version) {
|
||||||
ASSERT(ip_version == IPV4 || ip_version == IPV6);
|
ASSERT(ip_version == IPV4 || ip_version == IPV6);
|
||||||
char *ip_buf = malloc(MAX_ADDR_PORT_LENGTH);
|
char* ip_buf = malloc(MAX_ADDR_PORT_LENGTH);
|
||||||
memset(ip_buf, 0, MAX_ADDR_PORT_LENGTH);
|
memset(ip_buf, 0, MAX_ADDR_PORT_LENGTH);
|
||||||
const char *retval = NULL;
|
const char* retval = NULL;
|
||||||
|
|
||||||
if (ip_version == IPV4) {
|
if (ip_version == IPV4) {
|
||||||
retval = inet_ntop(AF_INET, &ip->in4, ip_buf, INET_ADDRSTRLEN);
|
retval = inet_ntop(AF_INET, &ip->in4, ip_buf, INET_ADDRSTRLEN);
|
||||||
} else if (ip_version == IPV6) {
|
}
|
||||||
|
else {
|
||||||
retval = inet_ntop(AF_INET6, &ip->in6, ip_buf, INET6_ADDRSTRLEN);
|
retval = inet_ntop(AF_INET6, &ip->in6, ip_buf, INET6_ADDRSTRLEN);
|
||||||
}
|
}
|
||||||
ASSERT(retval != NULL);
|
ASSERT(retval != NULL);
|
||||||
|
@ -72,19 +74,19 @@ struct mark_op {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void send_verdict(
|
static void send_verdict(
|
||||||
struct nf_queue *queue,
|
const struct nf_queue* queue,
|
||||||
struct nf_packet *pkt,
|
const struct nf_packet* pkt,
|
||||||
struct mark_op mark,
|
const struct mark_op mark,
|
||||||
struct pkt_buff *mangled_pkt_buff) {
|
struct pkt_buff* mangled_pkt_buff) {
|
||||||
struct nlmsghdr *nlh = nfqueue_put_header(pkt->queue_num, NFQNL_MSG_VERDICT);
|
struct nlmsghdr* nlh = nfqueue_put_header(pkt->queue_num, NFQNL_MSG_VERDICT);
|
||||||
if (nlh == NULL) {
|
if (nlh == NULL) {
|
||||||
syslog(LOG_ERR, "failed to put nfqueue header");
|
syslog(LOG_ERR, "failed to put nfqueue header");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
nfq_nlmsg_verdict_put(nlh, (int) pkt->packet_id, NF_ACCEPT);
|
nfq_nlmsg_verdict_put(nlh, pkt->packet_id, NF_ACCEPT);
|
||||||
|
|
||||||
if (mark.should_set) {
|
if (mark.should_set) {
|
||||||
struct nlattr *nest = mnl_attr_nest_start_check(nlh, SEND_BUF_LEN, NFQA_CT);
|
struct nlattr* nest = mnl_attr_nest_start_check(nlh, SEND_BUF_LEN, NFQA_CT);
|
||||||
if (nest == NULL) {
|
if (nest == NULL) {
|
||||||
syslog(LOG_ERR, "failed to put nfqueue attr");
|
syslog(LOG_ERR, "failed to put nfqueue attr");
|
||||||
goto end;
|
goto end;
|
||||||
|
@ -100,12 +102,12 @@ static void send_verdict(
|
||||||
nfq_nlmsg_verdict_put_pkt(nlh, pktb_data(mangled_pkt_buff), pktb_len(mangled_pkt_buff));
|
nfq_nlmsg_verdict_put_pkt(nlh, pktb_data(mangled_pkt_buff), pktb_len(mangled_pkt_buff));
|
||||||
}
|
}
|
||||||
|
|
||||||
__auto_type ret = mnl_socket_sendto(queue->nl_socket, nlh, nlh->nlmsg_len);
|
const __auto_type ret = mnl_socket_sendto(queue->nl_socket, nlh, nlh->nlmsg_len);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
syslog(LOG_ERR, "failed to send verdict: %s", strerror(errno));
|
syslog(LOG_ERR, "failed to send verdict: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
if (nlh != NULL) {
|
if (nlh != NULL) {
|
||||||
free(nlh);
|
free(nlh);
|
||||||
}
|
}
|
||||||
|
@ -114,66 +116,67 @@ static void send_verdict(
|
||||||
static bool conntrack_info_available = true;
|
static bool conntrack_info_available = true;
|
||||||
static bool cache_initialized = false;
|
static bool cache_initialized = false;
|
||||||
|
|
||||||
static void add_to_cache(struct nf_packet *pkt) {
|
static void add_to_cache(const struct nf_packet* pkt) {
|
||||||
char *ip_str = ip_to_str(&pkt->orig.dst, pkt->orig.dst_port, pkt->orig.ip_version);
|
char* ip_str = ip_to_str(&pkt->orig.dst, pkt->orig.dst_port, pkt->orig.ip_version);
|
||||||
cache_add(ip_str);
|
cache_add(ip_str);
|
||||||
free(ip_str);
|
free(ip_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct mark_op get_next_mark(struct nf_packet *pkt, bool has_ua) {
|
static struct mark_op get_next_mark(const struct nf_packet* pkt, const bool has_ua) {
|
||||||
if (!conntrack_info_available) {
|
if (!conntrack_info_available) {
|
||||||
return (struct mark_op) {false, 0};
|
return (struct mark_op){false, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
// I didn't think this will happen, but just in case
|
// I didn't think this will happen, but just in case
|
||||||
// firewall should already have a rule to return all marked with CONNMARK_NOT_HTTP packets
|
// firewall should already have a rule to return all marked with CONNMARK_NOT_HTTP packets
|
||||||
if (pkt->conn_mark == CONNMARK_NOT_HTTP) {
|
if (pkt->conn_mark == CONNMARK_NOT_HTTP) {
|
||||||
syslog(LOG_WARNING, "Packet has already been marked as not http. Maybe firewall rules are wrong?");
|
syslog(LOG_WARNING, "Packet has already been marked as not http. Maybe firewall rules are wrong?");
|
||||||
return (struct mark_op) {false, 0};
|
return (struct mark_op){false, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pkt->conn_mark == CONNMARK_HTTP) {
|
if (pkt->conn_mark == CONNMARK_HTTP) {
|
||||||
return (struct mark_op) {false, 0};
|
return (struct mark_op){false, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_ua) {
|
if (has_ua) {
|
||||||
return (struct mark_op) {true, CONNMARK_HTTP};
|
return (struct mark_op){true, CONNMARK_HTTP};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pkt->has_connmark || pkt->conn_mark == 0) {
|
if (!pkt->has_connmark || pkt->conn_mark == 0) {
|
||||||
return (struct mark_op) {true, CONNMARK_ESTIMATE_LOWER};
|
return (struct mark_op){true, CONNMARK_ESTIMATE_LOWER};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pkt->conn_mark == CONNMARK_ESTIMATE_VERDICT) {
|
if (pkt->conn_mark == CONNMARK_ESTIMATE_VERDICT) {
|
||||||
add_to_cache(pkt);
|
add_to_cache(pkt);
|
||||||
return (struct mark_op) {true, CONNMARK_NOT_HTTP};
|
return (struct mark_op){true, CONNMARK_NOT_HTTP};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pkt->conn_mark >= CONNMARK_ESTIMATE_LOWER && pkt->conn_mark <= CONNMARK_ESTIMATE_UPPER) {
|
if (pkt->conn_mark >= CONNMARK_ESTIMATE_LOWER && pkt->conn_mark <= CONNMARK_ESTIMATE_UPPER) {
|
||||||
return (struct mark_op) {true, pkt->conn_mark + 1};
|
return (struct mark_op){true, pkt->conn_mark + 1};
|
||||||
}
|
}
|
||||||
|
|
||||||
syslog(LOG_WARNING, "Unexpected connmark value: %d, Maybe other program has changed connmark?", pkt->conn_mark);
|
syslog(LOG_WARNING, "Unexpected connmark value: %d, Maybe other program has changed connmark?", pkt->conn_mark);
|
||||||
return (struct mark_op) {true, pkt->conn_mark + 1};
|
return (struct mark_op){true, pkt->conn_mark + 1};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool should_ignore(struct nf_packet *pkt) {
|
bool should_ignore(const struct nf_packet* pkt) {
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
char *ip_str = ip_to_str(&pkt->orig.dst, pkt->orig.dst_port, pkt->orig.ip_version);
|
char* ip_str = ip_to_str(&pkt->orig.dst, pkt->orig.dst_port, pkt->orig.ip_version);
|
||||||
retval = cache_contains(ip_str);
|
retval = cache_contains(ip_str);
|
||||||
free(ip_str);
|
free(ip_str);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_packet(struct nf_queue *queue, struct nf_packet *pkt) {
|
void handle_packet(const struct nf_queue* queue,const struct nf_packet* pkt) {
|
||||||
if (conntrack_info_available) {
|
if (conntrack_info_available) {
|
||||||
if (!pkt->has_conntrack) {
|
if (!pkt->has_conntrack) {
|
||||||
conntrack_info_available = false;
|
conntrack_info_available = false;
|
||||||
syslog(LOG_WARNING, "Packet has no conntrack. Switching to no cache mode.");
|
syslog(LOG_WARNING, "Packet has no conntrack. Switching to no cache mode.");
|
||||||
syslog(LOG_WARNING, "Note that this may lead to performance degradation. Especially on low-end routers.");
|
syslog(LOG_WARNING, "Note that this may lead to performance degradation. Especially on low-end routers.");
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
if (!cache_initialized) {
|
if (!cache_initialized) {
|
||||||
init_not_http_cache();
|
init_not_http_cache();
|
||||||
cache_initialized = true;
|
cache_initialized = true;
|
||||||
|
@ -181,9 +184,9 @@ void handle_packet(struct nf_queue *queue, struct nf_packet *pkt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pkt_buff *pkt_buff = NULL;
|
struct pkt_buff* pkt_buff = NULL;
|
||||||
if (conntrack_info_available && should_ignore(pkt)) {
|
if (conntrack_info_available && should_ignore(pkt)) {
|
||||||
send_verdict(queue, pkt, (struct mark_op) {true, CONNMARK_NOT_HTTP}, NULL);
|
send_verdict(queue, pkt, (struct mark_op){true, CONNMARK_NOT_HTTP}, NULL);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,45 +198,49 @@ void handle_packet(struct nf_queue *queue, struct nf_packet *pkt) {
|
||||||
|
|
||||||
if (conntrack_info_available) {
|
if (conntrack_info_available) {
|
||||||
type = pkt->orig.ip_version;
|
type = pkt->orig.ip_version;
|
||||||
} else {
|
}
|
||||||
__auto_type ip_hdr = nfq_ip_get_hdr(pkt_buff);
|
else {
|
||||||
|
const __auto_type ip_hdr = nfq_ip_get_hdr(pkt_buff);
|
||||||
if (ip_hdr == NULL) {
|
if (ip_hdr == NULL) {
|
||||||
type = IPV6;
|
type = IPV6;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
type = IPV4;
|
type = IPV4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == IPV4) {
|
if (type == IPV4) {
|
||||||
count_ipv4_packet();
|
count_ipv4_packet();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
count_ipv6_packet();
|
count_ipv6_packet();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == IPV4) {
|
if (type == IPV4) {
|
||||||
__auto_type ip_hdr = nfq_ip_get_hdr(pkt_buff);
|
const __auto_type ip_hdr = nfq_ip_get_hdr(pkt_buff);
|
||||||
if (nfq_ip_set_transport_header(pkt_buff, ip_hdr) < 0) {
|
if (nfq_ip_set_transport_header(pkt_buff, ip_hdr) < 0) {
|
||||||
syslog(LOG_ERR, "Failed to set ipv4 transport header");
|
syslog(LOG_ERR, "Failed to set ipv4 transport header");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
__auto_type ip_hdr = nfq_ip6_get_hdr(pkt_buff);
|
else {
|
||||||
|
const __auto_type ip_hdr = nfq_ip6_get_hdr(pkt_buff);
|
||||||
if (nfq_ip6_set_transport_header(pkt_buff, ip_hdr, IPPROTO_TCP) < 0) {
|
if (nfq_ip6_set_transport_header(pkt_buff, ip_hdr, IPPROTO_TCP) < 0) {
|
||||||
syslog(LOG_ERR, "Failed to set ipv6 transport header");
|
syslog(LOG_ERR, "Failed to set ipv6 transport header");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__auto_type tcp_hdr = nfq_tcp_get_hdr(pkt_buff);
|
const __auto_type tcp_hdr = nfq_tcp_get_hdr(pkt_buff);
|
||||||
if (tcp_hdr == NULL) {
|
if (tcp_hdr == NULL) {
|
||||||
// This packet is not tcp, pass it
|
// This packet is not tcp, pass it
|
||||||
send_verdict(queue, pkt, (struct mark_op) {false, 0}, NULL);
|
send_verdict(queue, pkt, (struct mark_op){false, 0}, NULL);
|
||||||
syslog(LOG_WARNING, "Received non-tcp packet. You may set wrong firewall rules.");
|
syslog(LOG_WARNING, "Received non-tcp packet. You may set wrong firewall rules.");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
__auto_type tcp_payload = nfq_tcp_get_payload(tcp_hdr, pkt_buff);
|
const __auto_type tcp_payload = nfq_tcp_get_payload(tcp_hdr, pkt_buff);
|
||||||
__auto_type tcp_payload_len = nfq_tcp_get_payload_len(tcp_hdr, pkt_buff);
|
const __auto_type tcp_payload_len = nfq_tcp_get_payload_len(tcp_hdr, pkt_buff);
|
||||||
|
|
||||||
if (tcp_payload == NULL || tcp_payload_len < USER_AGENT_MATCH_LENGTH) {
|
if (tcp_payload == NULL || tcp_payload_len < USER_AGENT_MATCH_LENGTH) {
|
||||||
send_verdict(queue, pkt, get_next_mark(pkt, false), NULL);
|
send_verdict(queue, pkt, get_next_mark(pkt, false), NULL);
|
||||||
|
@ -254,7 +261,7 @@ void handle_packet(struct nf_queue *queue, struct nf_packet *pkt) {
|
||||||
}
|
}
|
||||||
count_http_packet();
|
count_http_packet();
|
||||||
|
|
||||||
void *search_start = tcp_payload;
|
const void* search_start = tcp_payload;
|
||||||
unsigned int search_length = tcp_payload_len;
|
unsigned int search_length = tcp_payload_len;
|
||||||
bool has_ua = false;
|
bool has_ua = false;
|
||||||
|
|
||||||
|
@ -264,33 +271,34 @@ void handle_packet(struct nf_queue *queue, struct nf_packet *pkt) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *ua_pos = memncasemem(search_start, search_length, USER_AGENT_MATCH, USER_AGENT_MATCH_LENGTH);
|
char* ua_pos = memncasemem(search_start, search_length, USER_AGENT_MATCH, USER_AGENT_MATCH_LENGTH);
|
||||||
if (ua_pos == NULL) {
|
if (ua_pos == NULL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
has_ua = true;
|
has_ua = true;
|
||||||
|
|
||||||
void *ua_start = ua_pos + USER_AGENT_MATCH_LENGTH;
|
void* ua_start = ua_pos + USER_AGENT_MATCH_LENGTH;
|
||||||
|
|
||||||
// for non-standard user-agent like User-Agent:XXX with no space after colon
|
// for non-standard user-agent like User-Agent:XXX with no space after colon
|
||||||
if ((char) (*(char *) (ua_start)) == ' ') {
|
if (*(char *)ua_start == ' ') {
|
||||||
ua_start++;
|
ua_start++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ua_end = memchr(ua_start, '\r', tcp_payload_len - (ua_start - tcp_payload));
|
const void* ua_end = memchr(ua_start, '\r', tcp_payload_len - (ua_start - tcp_payload));
|
||||||
if (ua_end == NULL) {
|
if (ua_end == NULL) {
|
||||||
syslog(LOG_INFO, "User-Agent header is not terminated with \\r, not mangled.");
|
syslog(LOG_INFO, "User-Agent header is not terminated with \\r, not mangled.");
|
||||||
send_verdict(queue, pkt, get_next_mark(pkt, true), NULL);
|
send_verdict(queue, pkt, get_next_mark(pkt, true), NULL);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
unsigned int ua_len = ua_end - ua_start;
|
const unsigned int ua_len = ua_end - ua_start;
|
||||||
unsigned long ua_offset = ua_start - tcp_payload;
|
const unsigned long ua_offset = ua_start - tcp_payload;
|
||||||
|
|
||||||
// Looks it's impossible to mangle pocket failed, so we just drop it
|
// Looks it's impossible to mangle pocket failed, so we just drop it
|
||||||
if (type == IPV4) {
|
if (type == IPV4) {
|
||||||
nfq_tcp_mangle_ipv4(pkt_buff, ua_offset, ua_len, replacement_user_agent_string, ua_len);
|
nfq_tcp_mangle_ipv4(pkt_buff, ua_offset, ua_len, replacement_user_agent_string, ua_len);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
nfq_tcp_mangle_ipv6(pkt_buff, ua_offset, ua_len, replacement_user_agent_string, ua_len);
|
nfq_tcp_mangle_ipv6(pkt_buff, ua_offset, ua_len, replacement_user_agent_string, ua_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,7 +312,7 @@ void handle_packet(struct nf_queue *queue, struct nf_packet *pkt) {
|
||||||
|
|
||||||
send_verdict(queue, pkt, get_next_mark(pkt, has_ua), pkt_buff);
|
send_verdict(queue, pkt, get_next_mark(pkt, has_ua), pkt_buff);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
free(pkt->payload);
|
free(pkt->payload);
|
||||||
if (pkt_buff != NULL) {
|
if (pkt_buff != NULL) {
|
||||||
pktb_free(pkt_buff);
|
pktb_free(pkt_buff);
|
||||||
|
@ -321,4 +329,4 @@ void handle_packet(struct nf_queue *queue, struct nf_packet *pkt) {
|
||||||
#undef CONNMARK_ESTIMATE_VERDICT
|
#undef CONNMARK_ESTIMATE_VERDICT
|
||||||
|
|
||||||
#undef CONNMARK_NOT_HTTP
|
#undef CONNMARK_NOT_HTTP
|
||||||
#undef CONNMARK_HTTP
|
#undef CONNMARK_HTTP
|
||||||
|
|
|
@ -5,6 +5,6 @@
|
||||||
|
|
||||||
void init_handler();
|
void init_handler();
|
||||||
|
|
||||||
void handle_packet(struct nf_queue *queue, struct nf_packet *pkt);
|
void handle_packet(const struct nf_queue *queue, const struct nf_packet *pkt);
|
||||||
|
|
||||||
#endif //UA2F_HANDLER_H
|
#endif //UA2F_HANDLER_H
|
||||||
|
|
|
@ -41,8 +41,8 @@ void count_ipv6_packet() {
|
||||||
|
|
||||||
static char time_string_buffer[100];
|
static char time_string_buffer[100];
|
||||||
|
|
||||||
char *fill_time_string(double sec) {
|
char *fill_time_string(const double sec) {
|
||||||
int s = (int) sec;
|
const int s = (int) sec;
|
||||||
memset(time_string_buffer, 0, sizeof(time_string_buffer));
|
memset(time_string_buffer, 0, sizeof(time_string_buffer));
|
||||||
if (s <= 60) {
|
if (s <= 60) {
|
||||||
sprintf(time_string_buffer, "%d seconds", s);
|
sprintf(time_string_buffer, "%d seconds", s);
|
||||||
|
@ -61,7 +61,7 @@ char *fill_time_string(double sec) {
|
||||||
void try_print_statistics() {
|
void try_print_statistics() {
|
||||||
if (user_agent_packet_count / last_report_count == 2 || user_agent_packet_count - last_report_count >= 8192) {
|
if (user_agent_packet_count / last_report_count == 2 || user_agent_packet_count - last_report_count >= 8192) {
|
||||||
last_report_count = user_agent_packet_count;
|
last_report_count = user_agent_packet_count;
|
||||||
time_t current_t = time(NULL);
|
const time_t current_t = time(NULL);
|
||||||
syslog(
|
syslog(
|
||||||
LOG_INFO,
|
LOG_INFO,
|
||||||
"UA2F has handled %lld ua http, %lld http, %lld tcp. %lld ipv4, %lld ipv6 packets in %s.",
|
"UA2F has handled %lld ua http, %lld http, %lld tcp. %lld ipv4, %lld ipv6 packets in %s.",
|
||||||
|
|
|
@ -347,7 +347,7 @@ static bool inline read_ip_addr(struct nlattr *attr, int af, ip_address_t *ip_nu
|
||||||
void *addr = mnl_attr_get_payload(attr);
|
void *addr = mnl_attr_get_payload(attr);
|
||||||
if (addr == NULL)
|
if (addr == NULL)
|
||||||
return false;
|
return false;
|
||||||
int ip_ver = 0;
|
int ip_ver;
|
||||||
if (af == AF_INET) {
|
if (af == AF_INET) {
|
||||||
memset(&ip_num->ip, 0, sizeof(ip_num->ip));
|
memset(&ip_num->ip, 0, sizeof(ip_num->ip));
|
||||||
memcpy(&ip_num->ip4, addr, sizeof(uint32_t));
|
memcpy(&ip_num->ip4, addr, sizeof(uint32_t));
|
||||||
|
|
|
@ -15,12 +15,12 @@
|
||||||
|
|
||||||
volatile int should_exit = false;
|
volatile int should_exit = false;
|
||||||
|
|
||||||
void signal_handler(int signum) {
|
void signal_handler(const int signum) {
|
||||||
syslog(LOG_ERR, "Signal %s received, exiting...", strsignal(signum));
|
syslog(LOG_ERR, "Signal %s received, exiting...", strsignal(signum));
|
||||||
should_exit = true;
|
should_exit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(const int argc, char *argv[]) {
|
||||||
openlog("UA2F", LOG_PID, LOG_SYSLOG);
|
openlog("UA2F", LOG_PID, LOG_SYSLOG);
|
||||||
|
|
||||||
load_config();
|
load_config();
|
||||||
|
@ -36,12 +36,10 @@ int main(int argc, char *argv[]) {
|
||||||
signal(SIGSEGV, signal_handler);
|
signal(SIGSEGV, signal_handler);
|
||||||
signal(SIGABRT, signal_handler);
|
signal(SIGABRT, signal_handler);
|
||||||
|
|
||||||
struct nf_queue queue[1];
|
struct nf_queue queue[1] = {0};
|
||||||
memset(queue, 0, sizeof(struct nf_queue));
|
struct nf_buffer buf[1] = {0};
|
||||||
struct nf_buffer buf[1];
|
|
||||||
memset(buf, 0, sizeof(struct nf_buffer));
|
|
||||||
|
|
||||||
__auto_type ret = nfqueue_open(queue, QUEUE_NUM, 0);
|
const __auto_type ret = nfqueue_open(queue, QUEUE_NUM, 0);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
syslog(LOG_ERR, "Failed to open nfqueue");
|
syslog(LOG_ERR, "Failed to open nfqueue");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
void *memncasemem(const void *l, size_t l_len, const void *s, size_t s_len) {
|
void *memncasemem(const void *l, size_t l_len, const void *s, const size_t s_len) {
|
||||||
register char *cur, *last;
|
register char *cur, *last;
|
||||||
const char *cl = (const char *) l;
|
const char *cl = l;
|
||||||
const char *cs = (const char *) s;
|
const char *cs = s;
|
||||||
|
|
||||||
/* we need something to compare */
|
/* we need something to compare */
|
||||||
if (l_len == 0 || s_len == 0)
|
if (l_len == 0 || s_len == 0)
|
||||||
|
@ -36,11 +36,15 @@ void *memncasemem(const void *l, size_t l_len, const void *s, size_t s_len) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool probe_http_method(const char *p, int len, const char *opt) {
|
static bool probe_http_method(const char *p, const int len, const char *opt) {
|
||||||
|
if (len < strlen(opt)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return !strncmp(p, opt, strlen(opt));
|
return !strncmp(p, opt, strlen(opt));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_http_protocol(const char *p, unsigned int len) {
|
bool is_http_protocol(const char *p, const unsigned int len) {
|
||||||
bool pass = false;
|
bool pass = false;
|
||||||
|
|
||||||
#define PROBE_HTTP_METHOD(opt) if ((pass = probe_http_method(p, len, opt)) != false) return pass
|
#define PROBE_HTTP_METHOD(opt) if ((pass = probe_http_method(p, len, opt)) != false) return pass
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=dnsproxy
|
PKG_NAME:=dnsproxy
|
||||||
PKG_VERSION:=0.56.2
|
PKG_VERSION:=0.57.3
|
||||||
PKG_RELEASE:=2
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||||
PKG_SOURCE_URL:=https://codeload.github.com/AdguardTeam/dnsproxy/tar.gz/v$(PKG_VERSION)?
|
PKG_SOURCE_URL:=https://codeload.github.com/AdguardTeam/dnsproxy/tar.gz/v$(PKG_VERSION)?
|
||||||
PKG_HASH:=b20a77e88567fbcb80a07faa0f47aee7446b4d32ee7c17036fbdf07c03f05e3a
|
PKG_HASH:=1b938c714fe34fe665857e8c2f42b4305dd5ad0cd171aa6f935d77a49b4e6c72
|
||||||
|
|
||||||
PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
|
PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
|
||||||
PKG_LICENSE:=Apache-2.0
|
PKG_LICENSE:=Apache-2.0
|
||||||
|
|
Loading…
Reference in New Issue