void pythonmod_inform_super(struct module_qstate* qstate, int id, struct module_qstate* super) { struct pythonmod_env* pe = (struct pythonmod_env*)qstate->env->modinfo[id]; struct pythonmod_qstate* pq = (struct pythonmod_qstate*)qstate->minfo[id]; PyObject* py_qstate, *py_sqstate, *res; PyGILState_STATE gil = PyGILState_Ensure(); log_query_info(VERB_ALGO, "pythonmod: inform_super, sub is", &qstate->qinfo); log_query_info(VERB_ALGO, "super is", &super->qinfo); py_qstate = SWIG_NewPointerObj((void*) qstate, SWIGTYPE_p_module_qstate, 0); py_sqstate = SWIG_NewPointerObj((void*) super, SWIGTYPE_p_module_qstate, 0); res = PyObject_CallFunction(pe->func_inform, "iOOO", id, py_qstate, py_sqstate, pq->data); if (PyErr_Occurred()) { log_err("pythonmod: Exception occurred in function inform_super"); log_py_err(); qstate->ext_state[id] = module_error; } else if ((res == NULL) || (!PyObject_IsTrue(res))) { log_err("pythonmod: python returned bad code in inform_super"); qstate->ext_state[id] = module_error; } Py_XDECREF(res); Py_XDECREF(py_sqstate); Py_XDECREF(py_qstate); PyGILState_Release(gil); }
/** * Continue processing the mesh state at another module. * Handles module to modules tranfer of control. * Handles module finished. * @param mesh: the mesh area. * @param mstate: currently active mesh state. * Deleted if finished, calls _done and _supers to * send replies to clients and inform other mesh states. * This in turn may create additional runnable mesh states. * @param s: state at which the current module exited. * @param ev: the event sent to the module. * returned is the event to send to the next module. * @return true if continue processing at the new module. * false if not continued processing is needed. */ static int mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate, enum module_ext_state s, enum module_ev* ev) { mstate->num_activated++; if(mstate->num_activated > MESH_MAX_ACTIVATION) { /* module is looping. Stop it. */ log_err("internal error: looping module stopped"); log_query_info(VERB_QUERY, "pass error for qstate", &mstate->s.qinfo); s = module_error; } if(s == module_wait_module || s == module_restart_next) { /* start next module */ mstate->s.curmod++; if(mesh->mods.num == mstate->s.curmod) { log_err("Cannot pass to next module; at last module"); log_query_info(VERB_QUERY, "pass error for qstate", &mstate->s.qinfo); mstate->s.curmod--; return mesh_continue(mesh, mstate, module_error, ev); } if(s == module_restart_next) { fptr_ok(fptr_whitelist_mod_clear( mesh->mods.mod[mstate->s.curmod]->clear)); (*mesh->mods.mod[mstate->s.curmod]->clear) (&mstate->s, mstate->s.curmod); mstate->s.minfo[mstate->s.curmod] = NULL; } *ev = module_event_pass; return 1; } if(s == module_error && mstate->s.return_rcode == LDNS_RCODE_NOERROR) { /* error is bad, handle pass back up below */ mstate->s.return_rcode = LDNS_RCODE_SERVFAIL; } if(s == module_error || s == module_finished) { if(mstate->s.curmod == 0) { mesh_query_done(mstate); mesh_walk_supers(mesh, mstate); mesh_state_delete(&mstate->s); return 0; } /* pass along the locus of control */ mstate->s.curmod --; *ev = module_event_moddone; return 1; } return 0; }
/** debug print a packet that failed */ static void print_packet_rrsets(struct query_info* qinfo, struct reply_info* rep) { size_t i; ldns_rr_list* l; ldns_buffer* buf = ldns_buffer_new(65536); log_query_info(0, "failed query", qinfo); printf(";; ANSWER SECTION (%d rrsets)\n", (int)rep->an_numrrsets); for(i=0; i<rep->an_numrrsets; i++) { l = packed_rrset_to_rr_list(rep->rrsets[i], buf); printf("; rrset %d\n", (int)i); ldns_rr_list_print(stdout, l); ldns_rr_list_deep_free(l); } printf(";; AUTHORITY SECTION (%d rrsets)\n", (int)rep->ns_numrrsets); for(i=rep->an_numrrsets; i<rep->an_numrrsets+rep->ns_numrrsets; i++) { l = packed_rrset_to_rr_list(rep->rrsets[i], buf); printf("; rrset %d\n", (int)i); ldns_rr_list_print(stdout, l); ldns_rr_list_deep_free(l); } printf(";; ADDITIONAL SECTION (%d rrsets)\n", (int)rep->ar_numrrsets); for(i=rep->an_numrrsets+rep->ns_numrrsets; i<rep->rrset_count; i++) { l = packed_rrset_to_rr_list(rep->rrsets[i], buf); printf("; rrset %d\n", (int)i); ldns_rr_list_print(stdout, l); ldns_rr_list_deep_free(l); } printf(";; packet end\n"); ldns_buffer_free(buf); }
void cachedb_operate(struct module_qstate* qstate, enum module_ev event, int id, struct outbound_entry* outbound) { struct cachedb_env* ie = (struct cachedb_env*)qstate->env->modinfo[id]; struct cachedb_qstate* iq = (struct cachedb_qstate*)qstate->minfo[id]; verbose(VERB_QUERY, "cachedb[module %d] operate: extstate:%s event:%s", id, strextstate(qstate->ext_state[id]), strmodulevent(event)); if(iq) log_query_info(VERB_QUERY, "cachedb operate: query", &qstate->qinfo); /* perform cachedb state machine */ if((event == module_event_new || event == module_event_pass) && iq == NULL) { if(!cachedb_new(qstate, id)) { (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); return; } iq = (struct cachedb_qstate*)qstate->minfo[id]; } if(iq && (event == module_event_pass || event == module_event_new)) { cachedb_handle_query(qstate, iq, ie, id); return; } if(iq && (event == module_event_moddone)) { cachedb_handle_response(qstate, iq, ie, id); return; } if(iq && outbound) { /* cachedb does not need to process responses at this time * ignore it. cachedb_process_response(qstate, iq, ie, id, outbound, event); */ return; } 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)) { /* during priming, module done but we never started */ qstate->ext_state[id] = module_finished; return; } log_err("bad event for cachedb"); (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); }
void mesh_log_list(struct mesh_area* mesh) { char buf[30]; struct mesh_state* m; int num = 0; RBTREE_FOR(m, struct mesh_state*, &mesh->all) { snprintf(buf, sizeof(buf), "%d%s%s%s%s%s mod%d %s%s", num++, (m->s.is_priming)?"p":"", /* prime */ (m->s.query_flags&BIT_RD)?"RD":"", (m->s.query_flags&BIT_CD)?"CD":"", (m->super_set.count==0)?"d":"", /* detached */ (m->sub_set.count!=0)?"c":"", /* children */ m->s.curmod, (m->reply_list)?"rep":"", /*hasreply*/ (m->cb_list)?"cb":"" /* callbacks */ ); log_query_info(VERB_ALGO, buf, &m->s.qinfo); } }
/** debug print a packet that failed */ static void print_packet_rrsets(struct query_info* qinfo, struct reply_info* rep) { size_t i; log_query_info(0, "failed query", qinfo); printf(";; ANSWER SECTION (%d rrsets)\n", (int)rep->an_numrrsets); for(i=0; i<rep->an_numrrsets; i++) { printf("; rrset %d\n", (int)i); print_rrset(rep->rrsets[i]); } printf(";; AUTHORITY SECTION (%d rrsets)\n", (int)rep->ns_numrrsets); for(i=rep->an_numrrsets; i<rep->an_numrrsets+rep->ns_numrrsets; i++) { printf("; rrset %d\n", (int)i); print_rrset(rep->rrsets[i]); } printf(";; ADDITIONAL SECTION (%d rrsets)\n", (int)rep->ar_numrrsets); for(i=rep->an_numrrsets+rep->ns_numrrsets; i<rep->rrset_count; i++) { printf("; rrset %d\n", (int)i); print_rrset(rep->rrsets[i]); } printf(";; packet end\n"); }
void respip_operate(struct module_qstate* qstate, enum module_ev event, int id, struct outbound_entry* outbound) { struct respip_qstate* rq = (struct respip_qstate*)qstate->minfo[id]; log_query_info(VERB_QUERY, "respip operate: query", &qstate->qinfo); (void)outbound; if(event == module_event_new || event == module_event_pass) { if(!rq) { rq = regional_alloc_zero(qstate->region, sizeof(*rq)); if(!rq) goto servfail; rq->state = RESPIP_INIT; qstate->minfo[id] = rq; } if(rq->state == RESPIP_SUBQUERY_FINISHED) { qstate->ext_state[id] = module_finished; return; } verbose(VERB_ALGO, "respip: pass to next module"); qstate->ext_state[id] = module_wait_module; } else if(event == module_event_moddone) { /* If the reply may be subject to response-ip rewriting * according to the query type, check the actions. If a * rewrite is necessary, we'll replace the reply in qstate * with the new one. */ enum module_ext_state next_state = module_finished; if((qstate->qinfo.qtype == LDNS_RR_TYPE_A || qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA || qstate->qinfo.qtype == LDNS_RR_TYPE_ANY) && qstate->return_msg && qstate->return_msg->rep) { struct respip_action_info actinfo = {respip_none, NULL}; struct reply_info* new_rep = qstate->return_msg->rep; struct ub_packed_rrset_key* alias_rrset = NULL; if(!respip_rewrite_reply(&qstate->qinfo, qstate->client_info, qstate->return_msg->rep, &new_rep, &actinfo, &alias_rrset, 0, qstate->region)) { goto servfail; } if(actinfo.action != respip_none) { /* save action info for logging on a * per-front-end-query basis */ if(!(qstate->respip_action_info = regional_alloc_init(qstate->region, &actinfo, sizeof(actinfo)))) { log_err("out of memory"); goto servfail; } } else { qstate->respip_action_info = NULL; } if (new_rep == qstate->return_msg->rep && (actinfo.action == respip_deny || actinfo.action == respip_inform_deny)) { /* for deny-variant actions (unless response-ip * data is applied), mark the query state so * the response will be dropped for all * clients. */ qstate->is_drop = 1; } else if(alias_rrset) { if(!generate_cname_request(qstate, alias_rrset)) goto servfail; next_state = module_wait_subquery; } qstate->return_msg->rep = new_rep; } qstate->ext_state[id] = next_state; } else qstate->ext_state[id] = module_finished; return; servfail: qstate->return_rcode = LDNS_RCODE_SERVFAIL; qstate->return_msg = NULL; }