diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 009f86b..65ce0ca 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -106,6 +106,7 @@ jobs: - 4.19.322 - 4.4.302 - 3.10.108 + - 3.0.101 steps: - name: Checkout uses: actions/checkout@v4 diff --git a/src/args.c b/src/args.c index 828e0b0..5d10648 100644 --- a/src/args.c +++ b/src/args.c @@ -34,12 +34,18 @@ size_t ylgh_leftbuf = LOGGING_BUFSIZE; char *ylgh_curptr = ylgh_buf; int ylgh_ndnl = 0; +struct logging_config_t logging_conf = default_logging_config_set; + #ifdef KERNEL_SPACE static int errno = 0; #define strtol kstrtol #endif -struct config_t config = default_config_set; +void parse_global_lgconf(const struct config_t *config) { + logging_conf.syslog = config->syslog; + logging_conf.verbose = config->verbose; + logging_conf.instaflush = config->instaflush; +} static int parse_sni_domains(struct domains_list **dlist, const char *domains_str, size_t domains_strlen) { // Empty and shouldn't be used @@ -401,20 +407,19 @@ void print_usage(const char *argv0) { printf("\n"); } -int yparse_args(int argc, char *argv[]) { +int yparse_args(struct config_t *config, int argc, char *argv[]) { int opt; int optIdx = 0; optind=1, opterr=1, optreset=0; long num; int ret; - struct config_t rep_config; - ret = init_config(&rep_config); + ret = init_config(config); if (ret < 0) return ret; - struct section_config_t *default_section = rep_config.last_section; + struct section_config_t *default_section = config->last_section; - struct section_config_t *sect_config = rep_config.last_section; + struct section_config_t *sect_config = config->last_section; int sect_i = 0; sect_config->id = sect_i++; @@ -427,13 +432,13 @@ int yparse_args(int argc, char *argv[]) { while ((opt = getopt_long(argc, argv, "", long_opt, &optIdx)) != -1) { switch (opt) { case OPT_CLS: - free_config(rep_config); - ret = init_config(&rep_config); + free_config(config); + ret = init_config(config); if (ret < 0) return ret; - default_section = rep_config.last_section; + default_section = config->last_section; - sect_config = rep_config.last_section; + sect_config = config->last_section; sect_i = 0; sect_config->id = sect_i++; section_iter = SECT_ITER_DEFAULT; @@ -456,17 +461,17 @@ int yparse_args(int argc, char *argv[]) { break; #endif case OPT_TRACE: - rep_config.verbose = VERBOSE_TRACE; + config->verbose = VERBOSE_TRACE; break; case OPT_INSTAFLUSH: - rep_config.instaflush = 1; + config->instaflush = 1; break; case OPT_SILENT: - rep_config.verbose = VERBOSE_INFO; + config->verbose = VERBOSE_INFO; break; case OPT_NO_GSO: #ifndef KERNEL_SPACE - rep_config.use_gso = 0; + config->use_gso = 0; #else lgerr("--no-gso is not supported in kernel space"); goto invalid_opt; @@ -474,7 +479,7 @@ int yparse_args(int argc, char *argv[]) { break; case OPT_NO_CONNTRACK: #ifndef KERNEL_SPACE - rep_config.use_conntrack = 0; + config->use_conntrack = 0; #else lgerr("--no-conntrack is not supported in kernel space. Compile with make kmake EXTRA_CFLAGS=\"-DNO_CONNTRACK\" instead." ); goto invalid_opt; @@ -482,7 +487,7 @@ int yparse_args(int argc, char *argv[]) { break; case OPT_NO_IPV6: #ifndef KERNEL_SPACE - rep_config.use_ipv6 = 0; + config->use_ipv6 = 0; #else lgerr("--no-ipv6 argument is not available " "in the kernel module. " @@ -492,13 +497,13 @@ int yparse_args(int argc, char *argv[]) { #endif break; case OPT_DAEMONIZE: - rep_config.daemonize = 1; + config->daemonize = 1; break; case OPT_NOCLOSE: - rep_config.noclose = 1; + config->noclose = 1; break; case OPT_SYSLOG: - rep_config.syslog = 1; + config->syslog = 1; break; case OPT_THREADS: num = parse_numeric_option(optarg); @@ -506,7 +511,7 @@ int yparse_args(int argc, char *argv[]) { goto invalid_opt; } - rep_config.threads = num; + config->threads = num; break; case OPT_QUEUE_NUM: num = parse_numeric_option(optarg); @@ -514,7 +519,7 @@ int yparse_args(int argc, char *argv[]) { goto invalid_opt; } - rep_config.queue_start_num = num; + config->queue_start_num = num; break; case OPT_PACKET_MARK: num = parse_numeric_option(optarg); @@ -522,24 +527,24 @@ int yparse_args(int argc, char *argv[]) { goto invalid_opt; } - rep_config.mark = num; + config->mark = num; break; case OPT_CONNBYTES_LIMIT: num = parse_numeric_option(optarg); if (errno != 0 || num < 0) { goto invalid_opt; } - rep_config.connbytes_limit = num; + config->connbytes_limit = num; break; case OPT_START_SECTION: { struct section_config_t *nsect; - ret = init_section_config(&nsect, rep_config.last_section); + ret = init_section_config(&nsect, config->last_section); if (ret < 0) { goto error; } - rep_config.last_section->next = nsect; - rep_config.last_section = nsect; + config->last_section->next = nsect; + config->last_section = nsect; sect_config = nsect; sect_config->id = sect_i++; section_iter = SECT_ITER_INSIDE; @@ -821,16 +826,12 @@ int yparse_args(int argc, char *argv[]) { } - struct config_t old_config = config; - config = rep_config; - free_config(old_config); - errno = 0; return 0; #ifndef KERNEL_SPACE stop_exec: - free_config(rep_config); + free_config(config); errno = 0; return 1; #endif @@ -849,7 +850,7 @@ error: } errno = -ret; - free_config(rep_config); + free_config(config); return ret; } @@ -1027,56 +1028,56 @@ static size_t print_config_section(const struct section_config_t *section, char return buffer_size - buf_sz; } // Returns written buffer length -size_t print_config(char *buffer, size_t buffer_size) { +size_t print_config(const struct config_t *config, char *buffer, size_t buffer_size) { char *buf_ptr = buffer; size_t buf_sz = buffer_size; size_t sz; #ifndef KERNEL_SPACE - print_cnf_buf("--queue-num=%d", config.queue_start_num); - print_cnf_buf("--threads=%d", config.threads); + print_cnf_buf("--queue-num=%d", config->queue_start_num); + print_cnf_buf("--threads=%d", config->threads); #endif - print_cnf_buf("--packet-mark=%d", config.mark); + print_cnf_buf("--packet-mark=%d", config->mark); #ifndef KERNEL_SPACE - if (config.daemonize) { + if (config->daemonize) { print_cnf_buf("--daemonize"); } - if (config.syslog) { + if (config->syslog) { print_cnf_buf("--syslog"); } - if (config.noclose) { + if (config->noclose) { print_cnf_buf("--noclose"); } - if (!config.use_gso) { + if (!config->use_gso) { print_cnf_buf("--no-gso"); } - if (!config.use_conntrack) { + if (!config->use_conntrack) { print_cnf_buf("--no-conntrack"); } #endif #ifdef KERNEL_SPACE - print_cnf_buf("--connbytes-limit=%d", config.connbytes_limit); + print_cnf_buf("--connbytes-limit=%d", config->connbytes_limit); #endif - if (!config.use_ipv6) { + if (!config->use_ipv6) { print_cnf_buf("--no-ipv6"); } - if (config.verbose == VERBOSE_TRACE) { + if (config->verbose == VERBOSE_TRACE) { print_cnf_buf("--trace"); } - if (config.instaflush) { + if (config->instaflush) { print_cnf_buf("--instaflush"); } - if (config.verbose == VERBOSE_INFO) { + if (config->verbose == VERBOSE_INFO) { print_cnf_buf("--silent"); } - size_t wbuf_len = print_config_section(config.first_section, buf_ptr, buf_sz); + size_t wbuf_len = print_config_section(config->first_section, buf_ptr, buf_sz); buf_ptr += wbuf_len; buf_sz -= wbuf_len; - for (struct section_config_t *section = config.first_section->next; + for (struct section_config_t *section = config->first_section->next; section != NULL; section = section->next) { print_cnf_buf("--fbegin"); wbuf_len = print_config_section(section, buf_ptr, buf_sz); @@ -1088,12 +1089,12 @@ size_t print_config(char *buffer, size_t buffer_size) { return buffer_size - buf_sz; } -void print_welcome(void) { +void print_welcome(const struct config_t *config) { char *welcome_message = malloc(4000); if (welcome_message == NULL) return; - size_t sz = print_config(welcome_message, 4000); + size_t sz = print_config(config, welcome_message, 4000); printf("Running with flags: %.*s\n", (int)sz, welcome_message); free(welcome_message); } @@ -1156,8 +1157,8 @@ void free_config_section(struct section_config_t *section) { free(section); } -void free_config(struct config_t config) { - for (struct section_config_t *sct = config.last_section; sct != NULL;) { +void free_config(struct config_t *config) { + for (struct section_config_t *sct = config->last_section; sct != NULL;) { struct section_config_t *psct = sct->prev; free_config_section(sct); sct = psct; diff --git a/src/args.h b/src/args.h index 8860dbd..5ef19c9 100644 --- a/src/args.h +++ b/src/args.h @@ -24,8 +24,12 @@ void print_version(void); void print_usage(const char *argv0); -int yparse_args(int argc, char *argv[]); -size_t print_config(char *buffer, size_t buffer_size); +/** + * Initializes _config_ and parses args to it. + */ +int yparse_args(struct config_t *config, int argc, char *argv[]); +size_t print_config(const struct config_t *config, char *buffer, size_t buffer_size); +void parse_global_lgconf(const struct config_t *config); // Initializes configuration storage. int init_config(struct config_t *config); @@ -34,9 +38,9 @@ int init_section_config(struct section_config_t **section, struct section_config // Frees configuration section void free_config_section(struct section_config_t *config); // Frees sections under config -void free_config(struct config_t config); +void free_config(struct config_t *config); /* Prints starting messages */ -void print_welcome(void); +void print_welcome(const struct config_t *config); #endif /* ARGS_H */ diff --git a/src/config.h b/src/config.h index b2c57f3..2df8fe8 100644 --- a/src/config.h +++ b/src/config.h @@ -39,6 +39,14 @@ struct instance_config_t { }; extern struct instance_config_t instance_config; + +struct logging_config_t { + int verbose; + int instaflush; + int syslog; +}; +extern struct logging_config_t logging_conf; + struct udp_dport_range { uint16_t start; uint16_t end; @@ -132,9 +140,12 @@ struct config_t { struct section_config_t *first_section; struct section_config_t *last_section; + +#ifdef KERNEL_SPACE + struct kref refcount; +#endif }; -extern struct config_t config; #define ITER_CONFIG_SECTIONS(config, section) \ for (struct section_config_t *section = (config)->last_section; section != NULL; section = section->prev) @@ -208,7 +219,7 @@ if ((fake_bitmask) & strategy) #define DEFAULT_QUEUE_NUM 537 -#define MAX_PACKET_SIZE 8192 +#define MAX_PACKET_SIZE (1 << 16) #define DEFAULT_SNISTR "googlevideo.com,ggpht.com,ytimg.com,youtube.com,play.google.com,youtu.be,youtubei.googleapis.com,youtube.googleapis.com,youtubeembeddedplayer.googleapis.com,googleusercontent.com,gstatic.com,l.google.com" @@ -284,10 +295,11 @@ enum { .instaflush = 0, \ } -#define CONFIG_SET(config) \ -struct config_t config = default_config_set; \ -config->last_section = &(config.default_config) \ - +#define default_logging_config_set { \ + .verbose = VERBOSE_DEBUG, \ + .syslog = 0, \ + .instaflush = 0, \ +} struct ytb_conntrack { uint32_t mask; diff --git a/src/kytunblock.c b/src/kytunblock.c index 69c2cb8..ab27f2c 100644 --- a/src/kytunblock.c +++ b/src/kytunblock.c @@ -63,22 +63,21 @@ MODULE_DESCRIPTION("Linux kernel module for youtubeUnblock"); static struct socket *rawsocket; static struct socket *raw6socket; -static DEFINE_SPINLOCK(hot_config_spinlock); -static DEFINE_MUTEX(config_free_mutex); -static atomic_t hot_config_counter = ATOMIC_INIT(0); -// boolean flag for hot config replacement -// if 1, youtubeUnblock should stop processing -static atomic_t hot_config_rep = ATOMIC_INIT(0); - #define MAX_ARGC 1024 static char *argv[MAX_ARGC]; +static struct config_t *cur_config; + +static void config_release(struct kref *ref) +{ + struct config_t *config = container_of(ref, struct config_t, refcount); + free_config(config); + kfree(config); + pr_warn("Config release\n"); +} + static int params_set(const char *cval, const struct kernel_param *kp) { int ret; - ret = mutex_trylock(&config_free_mutex); - if (ret == 0) - return -EBUSY; - int cv_len = strlen(cval); if (cv_len >= 1 && cval[cv_len - 1] == '\n') { @@ -108,30 +107,36 @@ static int params_set(const char *cval, const struct kernel_param *kp) { } } - spin_lock(&hot_config_spinlock); - // lock netfilter youtubeUnblock - atomic_set(&hot_config_rep, 1); - spin_unlock(&hot_config_spinlock); - // lock config hot replacement process until all - // netfilter callbacks keep running - while (atomic_read(&hot_config_counter) > 0) {} + struct config_t *config; - ret = yparse_args(argc, argv); + config = kmalloc(sizeof(*config), GFP_KERNEL); + if (!config) { + ret = -ENOMEM; + goto ret_fval; + } - spin_lock(&hot_config_spinlock); - // relaunch youtubeUnblock - atomic_set(&hot_config_rep, 0); - spin_unlock(&hot_config_spinlock); + ret = yparse_args(config, argc, argv); + if (ret < 0) { + kfree(config); + goto ret_fval; + } + kref_init(&config->refcount); + + struct config_t *old_config = cur_config; + cur_config = config; + parse_global_lgconf(cur_config); + + kref_put(&old_config->refcount, config_release); + +ret_fval: kfree(val); - - mutex_unlock(&config_free_mutex); return ret; } static int params_get(char *buffer, const struct kernel_param *kp) { - size_t len = print_config(buffer, 4000); + size_t len = print_config(cur_config, buffer, 4000); return len; } @@ -154,7 +159,7 @@ static int open_raw_socket(void) { // That's funny, but this is how it is done in the kernel // https://elixir.bootlin.com/linux/v3.17.7/source/net/core/sock.c#L916 - rawsocket->sk->sk_mark=config.mark; + rawsocket->sk->sk_mark=cur_config->mark; return 0; @@ -164,10 +169,15 @@ err: static void close_raw_socket(void) { sock_release(rawsocket); + rawsocket = NULL; } static int send_raw_ipv4(const uint8_t *pkt, size_t pktlen) { int ret = 0; + if (rawsocket == NULL) { + return -ENOTSOCK; + + } if (pktlen > AVAILABLE_MTU) return -ENOMEM; struct iphdr *iph; @@ -216,7 +226,7 @@ static int open_raw6_socket(void) { // That's funny, but this is how it is done in the kernel // https://elixir.bootlin.com/linux/v3.17.7/source/net/core/sock.c#L916 - raw6socket->sk->sk_mark=config.mark; + raw6socket->sk->sk_mark=cur_config->mark; return 0; @@ -226,10 +236,16 @@ err: static void close_raw6_socket(void) { sock_release(raw6socket); + raw6socket = NULL; } static int send_raw_ipv6(const uint8_t *pkt, size_t pktlen) { int ret = 0; + if (raw6socket == NULL) { + return -ENOTSOCK; + + } + if (pktlen > AVAILABLE_MTU) return -ENOMEM; struct ip6_hdr *iph; @@ -303,7 +319,7 @@ static int send_raw_socket(const uint8_t *pkt, size_t pktlen) { else { goto erret_lc; } - + free(buff1); free(buff2); return sent; @@ -464,18 +480,10 @@ static NF_CALLBACK(ykb_nf_hook, skb) { uint8_t *data_buf = NULL; int nf_verdict = NF_ACCEPT; - spin_lock(&hot_config_spinlock); - // if set flag to disable processing, - // explicitly accept all packets - if (atomic_read(&hot_config_rep)) { - spin_unlock(&hot_config_spinlock); - return NF_ACCEPT; - } else { - atomic_inc(&hot_config_counter); - } - spin_unlock(&hot_config_spinlock); + struct config_t *config = cur_config; + kref_get(&config->refcount); - if ((skb->mark & config.mark) == config.mark) { + if ((skb->mark & config->mark) == config->mark) { goto send_verdict; } @@ -492,7 +500,7 @@ static NF_CALLBACK(ykb_nf_hook, skb) { lgtrace("[TRACE] conntrack_parse error code\n"); } - if (config.connbytes_limit != 0 && yct_is_mask_attr(YCTATTR_ORIG_PACKETS, &pd.yct) && pd.yct.orig_packets > config.connbytes_limit) + if (config->connbytes_limit != 0 && yct_is_mask_attr(YCTATTR_ORIG_PACKETS, &pd.yct) && pd.yct.orig_packets > config->connbytes_limit) goto send_verdict; @@ -514,7 +522,7 @@ static NF_CALLBACK(ykb_nf_hook, skb) { pd.payload_len = skb->len; - int vrd = process_packet(&pd); + int vrd = process_packet(config, &pd); switch(vrd) { case PKT_ACCEPT: @@ -528,7 +536,7 @@ static NF_CALLBACK(ykb_nf_hook, skb) { send_verdict: kfree(data_buf); - atomic_dec(&hot_config_counter); + kref_put(&config->refcount, config_release); return nf_verdict; } @@ -581,12 +589,18 @@ static int __init ykb_init(void) { #ifdef NO_IPV6 lgwarning("IPv6 is disabled."); #endif - - ret = init_config(&config); + cur_config = kmalloc(sizeof(*cur_config), GFP_KERNEL); + if (!cur_config) { + return -ENOMEM; + } + ret = init_config(cur_config); if (ret < 0) { + kfree(cur_config); goto err; } + kref_init(&cur_config->refcount); + ret = open_raw_socket(); if (ret < 0) { lgerror(ret, "ipv4 rawsocket initialization failed!"); @@ -621,36 +635,24 @@ err_close_sock: err_close4_sock: close_raw_socket(); err_config: - free_config(config); + kref_put(&cur_config->refcount, config_release); err: return ret; } -static void __exit ykb_destroy(void) { - mutex_lock(&config_free_mutex); - // acquire all locks. - spin_lock(&hot_config_spinlock); - // lock netfilter youtubeUnblock - atomic_set(&hot_config_rep, 1); - spin_unlock(&hot_config_spinlock); - - // wait until all - // netfilter callbacks keep running - while (atomic_read(&hot_config_counter) > 0) {} - +static void __exit ykb_destroy(void) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0) unregister_pernet_subsys(&ykb_pernet_ops); #else nf_unregister_hooks(ykb_hook_ops, ykb_hooks_sz); #endif - #ifndef NO_IPV6 close_raw6_socket(); #endif close_raw_socket(); - free_config(config); + kref_put(&cur_config->refcount, config_release); lginfo("youtubeUnblock kernel module destroyed.\n"); } diff --git a/src/logging.h b/src/logging.h index 482ebc1..7aaf982 100644 --- a/src/logging.h +++ b/src/logging.h @@ -21,29 +21,10 @@ #define LOGGING_H #include "config.h" -#ifdef KERNEL_SPACE -#include -#include -#define printf pr_info -#define perror pr_err - #define LOG_ERR KERN_ERR #define LOG_INFO KERN_INFO #define LOG_WARN KERN_WARNING -#define print_message(level, msg, ...) \ - (printk(level msg, ##__VA_ARGS__)) - -#else -#include // IWYU pragma: export -#include -#include - -#define print_message(level, msg, ...) \ - (config.syslog ? (void)(syslog((level), msg, ##__VA_ARGS__)) : (void)(printf(msg, ##__VA_ARGS__) + fflush(stdout))) - -#endif /* PROGRAM_SPACE */ - /** * Defined in args.c */ @@ -53,7 +34,27 @@ extern size_t ylgh_leftbuf; extern char *ylgh_curptr; extern int ylgh_ndnl; -#define LOG_LEVEL (config.verbose) +#define LOG_LEVEL (logging_conf.verbose) +#define DO_INSTAFLUSH (logging_conf.instaflush) +#define DO_SYSLOG (logging_conf.syslog) + +#ifdef KERNEL_SPACE +#include +#include +#define printf pr_info +#define perror pr_err +#define print_message(level, msg, ...) \ + (printk(level msg, ##__VA_ARGS__)) + +#else +#include // IWYU pragma: export +#include +#include + +#define print_message(level, msg, ...) \ + (DO_SYSLOG ? (void)(syslog((level), msg, ##__VA_ARGS__)) : (void)(printf(msg, ##__VA_ARGS__) + fflush(stdout))) + +#endif /* PROGRAM_SPACE */ /** * For flushing only. Use log_buf_write for writing. @@ -128,7 +129,7 @@ extern int ylgh_ndnl; if (LOG_LEVEL >= VERBOSE_TRACE) { \ ylgh_ndnl = 1; \ log_buf(LOG_INFO, msg, ##__VA_ARGS__); \ - if (config.instaflush) { \ + if (DO_INSTAFLUSH) { \ log_buf_flush(LOG_INFO); \ } \ } \ diff --git a/src/mangle.c b/src/mangle.c index 6434380..5a89ed5 100644 --- a/src/mangle.c +++ b/src/mangle.c @@ -32,7 +32,7 @@ #include "linux/inet.h" #endif -int process_packet(const struct packet_data *pd) { +int process_packet(const struct config_t *config, const struct packet_data *pd) { const uint8_t *raw_payload = pd->payload; uint32_t raw_payload_len = pd->payload_len; @@ -65,7 +65,7 @@ int process_packet(const struct packet_data *pd) { transport_proto = iph->protocol; - } else if (ipver == IP6VERSION && config.use_ipv6) { + } else if (ipver == IP6VERSION && config->use_ipv6) { ret = ip6_payload_split((uint8_t *)raw_payload, raw_payload_len, (struct ip6_hdr **)&ip6h, &iph_len, (uint8_t **)&ip_payload, &ip_payload_len); @@ -151,7 +151,7 @@ int process_packet(const struct packet_data *pd) { int verdict = PKT_CONTINUE; - ITER_CONFIG_SECTIONS(&config, section) { + ITER_CONFIG_SECTIONS(config, section) { lgtrace_wr("Section #%d: ", CONFIG_SECTION_NUMBER(section)); switch (transport_proto) { diff --git a/src/mangle.h b/src/mangle.h index 77567fd..1228867 100644 --- a/src/mangle.h +++ b/src/mangle.h @@ -33,7 +33,7 @@ * Processes the packet and returns verdict. * This is the primary function that traverses the packet. */ -int process_packet(const struct packet_data *pd); +int process_packet(const struct config_t *config, const struct packet_data *pd); /** diff --git a/src/youtubeUnblock.c b/src/youtubeUnblock.c index 9b941df..7bb41ec 100644 --- a/src/youtubeUnblock.c +++ b/src/youtubeUnblock.c @@ -59,6 +59,8 @@ int rawsocket = -2; pthread_mutex_t raw6socket_lock; int raw6socket = -2; +static struct config_t *cur_config = NULL; + static int open_socket(struct mnl_socket **_nl) { struct mnl_socket *nl = NULL; nl = mnl_socket_open(NETLINK_NETFILTER); @@ -106,7 +108,7 @@ static int open_raw_socket(void) { return -1; } - int mark = config.mark; + int mark = cur_config->mark; if (setsockopt(rawsocket, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0) { lgerror(-errno, "setsockopt(SO_MARK, %d) failed", mark); @@ -158,7 +160,7 @@ static int open_raw6_socket(void) { return -1; } - int mark = config.mark; + int mark = cur_config->mark; if (setsockopt(raw6socket, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0) { lgerror(-errno, "setsockopt(SO_MARK, %d) failed", mark); @@ -442,14 +444,14 @@ static int send_raw_ipv4(const uint8_t *pkt, size_t pktlen) { } }; - if (config.threads != 1) + if (cur_config->threads != 1) pthread_mutex_lock(&rawsocket_lock); int sent = sendto(rawsocket, pkt, pktlen, MSG_DONTWAIT, (struct sockaddr *)&daddr, sizeof(daddr)); - if (config.threads != 1) + if (cur_config->threads != 1) pthread_mutex_unlock(&rawsocket_lock); /* The function will return -errno on error as well as errno value set itself */ @@ -477,7 +479,7 @@ static int send_raw_ipv6(const uint8_t *pkt, size_t pktlen) { .sin6_addr = iph->ip6_dst }; - if (config.threads != 1) + if (cur_config->threads != 1) pthread_mutex_lock(&rawsocket_lock); int sent = sendto(raw6socket, @@ -486,7 +488,7 @@ static int send_raw_ipv6(const uint8_t *pkt, size_t pktlen) { lgtrace_addp("rawsocket sent %d", sent); - if (config.threads != 1) + if (cur_config->threads != 1) pthread_mutex_unlock(&rawsocket_lock); /* The function will return -errno on error as well as errno value set itself */ @@ -666,8 +668,8 @@ static int queue_cb(const struct nlmsghdr *nlh, void *data) { if (attr[NFQA_MARK] != NULL) { // Skip packets sent by rawsocket to escape infinity loop. - if ((ntohl(mnl_attr_get_u32(attr[NFQA_MARK])) & config.mark) == - config.mark) { + if ((ntohl(mnl_attr_get_u32(attr[NFQA_MARK])) & cur_config->mark) == + cur_config->mark) { return fallback_accept_packet(id, *qdata); } } @@ -690,7 +692,7 @@ static int queue_cb(const struct nlmsghdr *nlh, void *data) { ct_out: verdnlh = nfq_nlmsg_put(buf, NFQNL_MSG_VERDICT, qdata->queue_num); - ret = process_packet(&packet); + ret = process_packet(cur_config, &packet); switch (ret) { case PKT_DROP: @@ -748,7 +750,7 @@ int init_queue(int queue_num) { goto die; } - if (config.use_ipv6) { + if (cur_config->use_ipv6) { nlh = nfq_nlmsg_put(buf, NFQNL_MSG_CONFIG, queue_num); nfq_nlmsg_cfg_put_cmd(nlh, PF_INET6, NFQNL_CFG_CMD_PF_UNBIND); @@ -781,10 +783,10 @@ int init_queue(int queue_num) { unsigned int cfg_flags = NFQA_CFG_F_GSO | NFQA_CFG_F_CONNTRACK | NFQA_CFG_F_FAIL_OPEN; unsigned int cfg_mask = 0; - if (config.use_gso) { + if (cur_config->use_gso) { cfg_mask |= NFQA_CFG_F_GSO; } - if (config.use_conntrack) { + if (cur_config->use_conntrack) { cfg_mask |= NFQA_CFG_F_CONNTRACK; } cfg_mask |= NFQA_CFG_F_FAIL_OPEN; @@ -875,7 +877,9 @@ struct instance_config_t instance_config = { int main(int argc, char *argv[]) { int ret; - if ((ret = yparse_args(argc, argv)) != 0) { + struct config_t config; + + if ((ret = yparse_args(&config, argc, argv)) != 0) { if (ret < 0) { lgerror(-errno, "Unable to parse args"); exit(EXIT_FAILURE); @@ -884,7 +888,10 @@ int main(int argc, char *argv[]) { } print_version(); - print_welcome(); + print_welcome(&config); + + parse_global_lgconf(&config); + cur_config = &config; if (open_raw_socket() < 0) {