]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
fix segmentation fault 28/head
authorKevin Chou <k9982874@gmail.com>
Sat, 18 May 2019 05:48:49 +0000 (13:48 +0800)
committerKevin Chou <k9982874@gmail.com>
Sat, 18 May 2019 05:48:49 +0000 (13:48 +0800)
ipset/ipset.c

index 55ef05c3d3aaea42c5622f37db266a085a891fd6..fb16c06a3df2590681c78f60f965b68696c04e51 100755 (executable)
@@ -33,6 +33,23 @@ static int error_response(struct module_qstate* qstate, int id, int rcode) {
        return 0;
 }
 
+static struct mnl_socket * open_mnl_socket() {
+       struct mnl_socket *mnl;
+
+       mnl = mnl_socket_open(NETLINK_NETFILTER);
+       if (!mnl) {
+               log_err("ipset: could not open netfilter.");
+               return NULL;
+       }
+
+       if (mnl_socket_bind(mnl, 0, MNL_SOCKET_AUTOPID) < 0) {
+               mnl_socket_close(mnl);
+               log_err("ipset: could not bind netfilter.");
+               return NULL;
+       }
+       return mnl;
+}
+
 static int add_to_ipset(struct mnl_socket *mnl, const char *setname, const void *ipaddr, int af) {
        struct nlmsghdr *nlh;
        struct nfgenmsg *nfg;
@@ -98,8 +115,14 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg, stru
        uint8_t *rr_data;
 
        mnl = (struct mnl_socket *)ie->mnl;
-       if (mnl == NULL) {
-               return -1;
+       if (!mnl) {
+               // retry to create mnl socket
+               mnl = open_mnl_socket();
+               if (!mnl) {
+                       return -1;
+               }
+
+               ie->mnl = mnl;
        }
 
        for (i = 0; i < return_msg->rep->rrset_count; ++i) {
@@ -119,7 +142,7 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg, stru
                        }
                }
 
-               if (setname != NULL) {
+               if (setname) {
                        dlen = sldns_wire2str_dname_buf(rrset->rk.dname, rrset->rk.dname_len, dname, BUFF_LEN);
                        if (dlen == 0) {
                                log_err("bad domain name");
@@ -146,6 +169,9 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg, stru
                                                                ret = add_to_ipset(mnl, setname, rr_data + 2, af);
                                                                if (ret < 0) {
                                                                        log_err("ipset: could not add %s into %s", dname, setname);
+
+                                                                       mnl_socket_close(mnl);
+                                                                       ie->mnl = NULL;
                                                                        break;
                                                                }
                                                        }
@@ -154,58 +180,48 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg, stru
                                        }
                                }
                        }
-               }
+               }
        }
 
        return 0;
 }
 
 int ipset_init(struct module_env* env, int id) {
-       struct mnl_socket *mnl;
+       struct ipset_env *ipset_env;
 
-       struct ipset_env *ipset_env = (struct ipset_env *)calloc(1,
-               sizeof(struct ipset_env));
-       if(!ipset_env) {
+       ipset_env = (struct ipset_env *)calloc(1, sizeof(struct ipset_env));
+       if (!ipset_env) {
                log_err("malloc failure");
                return 0;
        }
-       env->modinfo[id] = (void*)ipset_env;
+
+       env->modinfo[id] = (void *)ipset_env;
+
+       ipset_env->mnl == NULL;
 
        ipset_env->name_v4 = env->cfg->ipset_name_v4;
        ipset_env->name_v6 = env->cfg->ipset_name_v6;
 
-       ipset_env->v4_enabled = (ipset_env->name_v4 == NULL) || (strlen(ipset_env->name_v4) == 0) ? 0 : 1;
-       ipset_env->v6_enabled = (ipset_env->name_v6 == NULL) || (strlen(ipset_env->name_v6) == 0) ? 0 : 1;
+       ipset_env->v4_enabled = !ipset_env->name_v4 || (strlen(ipset_env->name_v4) == 0) ? 0 : 1;
+       ipset_env->v6_enabled = !ipset_env->name_v6 || (strlen(ipset_env->name_v6) == 0) ? 0 : 1;
 
        if ((ipset_env->v4_enabled < 1) && (ipset_env->v6_enabled < 1)) {
                log_err("ipset: set name no configuration?");
                return 0;
        }
 
-       mnl = mnl_socket_open(NETLINK_NETFILTER);
-       if (mnl <= 0) {
-               log_err("ipset: could not open netfilter.");
-               return 0;
-       }
-
-       if (mnl_socket_bind(mnl, 0, MNL_SOCKET_AUTOPID) < 0) {
-               mnl_socket_close(mnl);
-               log_err("ipset: could not bind netfilter.");
-               return 0;
-       }
-
-       ipset_env->mnl = mnl;
-
        return 1;
 }
 
 void ipset_deinit(struct module_env *env, int id) {
        struct mnl_socket *mnl;
+       struct ipset_env *ipset_env;
 
-       struct ipset_env* ipset_env;
-       if(!env || !env->modinfo[id])
+       if (!env || !env->modinfo[id]) {
                return;
-       ipset_env = (struct ipset_env*)env->modinfo[id];
+       }
+
+       ipset_env = (struct ipset_env *)env->modinfo[id];
 
        mnl = (struct mnl_socket *)ipset_env->mnl;
        if (mnl) {
@@ -218,11 +234,13 @@ void ipset_deinit(struct module_env *env, int id) {
 }
 
 static int ipset_new(struct module_qstate* qstate, int id) {
-       struct ipset_qstate* iq = (struct ipset_qstate*)regional_alloc(
+       struct ipset_qstate *iq = (struct ipset_qstate *)regional_alloc(
                qstate->region, sizeof(struct ipset_qstate));
        qstate->minfo[id] = iq;
-       if(!iq)
+       if (!iq) {
                return 0;
+       }
+
        memset(iq, 0, sizeof(*iq));
        /* initialise it */
        /* TODO */
@@ -236,42 +254,47 @@ void ipset_operate(struct module_qstate *qstate, enum module_ev event, int id,
        struct ipset_qstate *iq = (struct ipset_qstate *)qstate->minfo[id];
        verbose(VERB_QUERY, "ipset[module %d] operate: extstate:%s event:%s",
                id, strextstate(qstate->ext_state[id]), strmodulevent(event));
-       if(iq) log_query_info(VERB_QUERY, "ipset operate: query",
-               &qstate->qinfo);
+       if (iq) {
+               log_query_info(VERB_QUERY, "ipset operate: query", &qstate->qinfo);
+       }
 
        /* perform ipset state machine */
-       if((event == module_event_new || event == module_event_pass) &&
-               iq == NULL) {
-               if(!ipset_new(qstate, id)) {
+       if ((event == module_event_new || event == module_event_pass) && !iq) {
+               if (!ipset_new(qstate, id)) {
                        (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
                        return;
                }
                iq = (struct ipset_qstate*)qstate->minfo[id];
        }
 
-       if(iq && (event == module_event_pass || event == module_event_new)) {
+       if (iq && (event == module_event_pass || event == module_event_new)) {
                qstate->ext_state[id] = module_wait_module;
                return;
        }
 
-       if(iq && (event == module_event_moddone)) {
-               ipset_update(qstate->env, qstate->return_msg, ie);
+       if (iq && (event == module_event_moddone)) {
+               if (qstate->return_msg && qstate->return_msg->rep) {
+                       ipset_update(qstate->env, qstate->return_msg, ie);
+               }
                qstate->ext_state[id] = module_finished;
                return;
        }
-       if(iq && outbound) {
+
+       if (iq && outbound) {
                /* ipset does not need to process responses at this time
                 * ignore it.
                ipset_process_response(qstate, iq, ie, id, outbound, event);
                */
                return;
        }
-       if(event == module_event_error) {
+
+       if (event == module_event_error) {
                verbose(VERB_ALGO, "got called with event error, giving up");
                (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
                return;
        }
-       if(!iq && (event == module_event_moddone)) {
+
+       if (!iq && (event == module_event_moddone)) {
                /* during priming, module done but we never started */
                qstate->ext_state[id] = module_finished;
                return;
@@ -281,25 +304,26 @@ void ipset_operate(struct module_qstate *qstate, enum module_ev event, int id,
        (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
 }
 
-void ipset_inform_super(struct module_qstateATTR_UNUSED(qstate),
-       int ATTR_UNUSED(id), struct module_qstateATTR_UNUSED(super)) {
+void ipset_inform_super(struct module_qstate *ATTR_UNUSED(qstate),
+       int ATTR_UNUSED(id), struct module_qstate *ATTR_UNUSED(super)) {
        /* ipset does not use subordinate requests at this time */
        verbose(VERB_ALGO, "ipset inform_super was called");
 }
 
-void ipset_clear(struct module_qstateqstate, int id) {
-       struct cachedb_qstateiq;
-       if(!qstate)
+void ipset_clear(struct module_qstate *qstate, int id) {
+       struct cachedb_qstate *iq;
+       if (!qstate) {
                return;
-       iq = (struct cachedb_qstate*)qstate->minfo[id];
-       if(iq) {
+       }
+       iq = (struct cachedb_qstate *)qstate->minfo[id];
+       if (iq) {
                /* free contents of iq */
                /* TODO */
        }
        qstate->minfo[id] = NULL;
 }
 
-size_t ipset_get_mem(struct module_envenv, int id) {
+size_t ipset_get_mem(struct module_env *env, int id) {
        struct ipset_env *ie = (struct ipset_env *)env->modinfo[id];
        if (!ie) {
                return 0;
@@ -320,4 +344,3 @@ struct module_func_block * ipset_get_funcblock(void) {
        return &ipset_block;
 }
 
-