Deleted Added
full compact
mesh.c (266114) mesh.c (276605)
1/*
2 * services/mesh.c - deal with mesh of query states and handle events for that.
3 *
4 * Copyright (c) 2007, NLnet Labs. All rights reserved.
5 *
6 * This software is open source.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 118 unchanged lines hidden (view full) ---

127 struct mesh_state* a = (struct mesh_state*)ap;
128 struct mesh_state* b = (struct mesh_state*)bp;
129
130 if(a->s.is_priming && !b->s.is_priming)
131 return -1;
132 if(!a->s.is_priming && b->s.is_priming)
133 return 1;
134
1/*
2 * services/mesh.c - deal with mesh of query states and handle events for that.
3 *
4 * Copyright (c) 2007, NLnet Labs. All rights reserved.
5 *
6 * This software is open source.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 118 unchanged lines hidden (view full) ---

127 struct mesh_state* a = (struct mesh_state*)ap;
128 struct mesh_state* b = (struct mesh_state*)bp;
129
130 if(a->s.is_priming && !b->s.is_priming)
131 return -1;
132 if(!a->s.is_priming && b->s.is_priming)
133 return 1;
134
135 if(a->s.is_valrec && !b->s.is_valrec)
136 return -1;
137 if(!a->s.is_valrec && b->s.is_valrec)
138 return 1;
139
135 if((a->s.query_flags&BIT_RD) && !(b->s.query_flags&BIT_RD))
136 return -1;
137 if(!(a->s.query_flags&BIT_RD) && (b->s.query_flags&BIT_RD))
138 return 1;
139
140 if((a->s.query_flags&BIT_CD) && !(b->s.query_flags&BIT_CD))
141 return -1;
142 if(!(a->s.query_flags&BIT_CD) && (b->s.query_flags&BIT_CD))

--- 129 unchanged lines hidden (view full) ---

272 /* no space for new item */
273 return 0;
274}
275
276void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
277 uint16_t qflags, struct edns_data* edns, struct comm_reply* rep,
278 uint16_t qid)
279{
140 if((a->s.query_flags&BIT_RD) && !(b->s.query_flags&BIT_RD))
141 return -1;
142 if(!(a->s.query_flags&BIT_RD) && (b->s.query_flags&BIT_RD))
143 return 1;
144
145 if((a->s.query_flags&BIT_CD) && !(b->s.query_flags&BIT_CD))
146 return -1;
147 if(!(a->s.query_flags&BIT_CD) && (b->s.query_flags&BIT_CD))

--- 129 unchanged lines hidden (view full) ---

277 /* no space for new item */
278 return 0;
279}
280
281void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
282 uint16_t qflags, struct edns_data* edns, struct comm_reply* rep,
283 uint16_t qid)
284{
280 /* do not use CD flag from user for mesh state, we want the CD-query
281 * to receive validation anyway, to protect out cache contents and
282 * avoid bad-data in this cache that a downstream validator cannot
283 * remove from this cache */
284 struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&BIT_RD, 0);
285 struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
285 int was_detached = 0;
286 int was_noreply = 0;
287 int added = 0;
288 /* does this create a new reply state? */
289 if(!s || s->list_select == mesh_no_list) {
290 if(!mesh_make_new_space(mesh, rep->c->buffer)) {
291 verbose(VERB_ALGO, "Too many queries. dropping "
292 "incoming query.");

--- 13 unchanged lines hidden (view full) ---

306 return;
307 }
308 }
309 /* see if it already exists, if not, create one */
310 if(!s) {
311#ifdef UNBOUND_DEBUG
312 struct rbnode_t* n;
313#endif
286 int was_detached = 0;
287 int was_noreply = 0;
288 int added = 0;
289 /* does this create a new reply state? */
290 if(!s || s->list_select == mesh_no_list) {
291 if(!mesh_make_new_space(mesh, rep->c->buffer)) {
292 verbose(VERB_ALGO, "Too many queries. dropping "
293 "incoming query.");

--- 13 unchanged lines hidden (view full) ---

307 return;
308 }
309 }
310 /* see if it already exists, if not, create one */
311 if(!s) {
312#ifdef UNBOUND_DEBUG
313 struct rbnode_t* n;
314#endif
314 s = mesh_state_create(mesh->env, qinfo, qflags&BIT_RD, 0);
315 s = mesh_state_create(mesh->env, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
315 if(!s) {
316 log_err("mesh_state_create: out of memory; SERVFAIL");
317 error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
318 qinfo, qid, qflags, edns);
319 comm_point_send_reply(rep);
320 return;
321 }
322#ifdef UNBOUND_DEBUG

--- 47 unchanged lines hidden (view full) ---

370 mesh_run(mesh, s, module_event_new, NULL);
371}
372
373int
374mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
375 uint16_t qflags, struct edns_data* edns, sldns_buffer* buf,
376 uint16_t qid, mesh_cb_func_t cb, void* cb_arg)
377{
316 if(!s) {
317 log_err("mesh_state_create: out of memory; SERVFAIL");
318 error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
319 qinfo, qid, qflags, edns);
320 comm_point_send_reply(rep);
321 return;
322 }
323#ifdef UNBOUND_DEBUG

--- 47 unchanged lines hidden (view full) ---

371 mesh_run(mesh, s, module_event_new, NULL);
372}
373
374int
375mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
376 uint16_t qflags, struct edns_data* edns, sldns_buffer* buf,
377 uint16_t qid, mesh_cb_func_t cb, void* cb_arg)
378{
378 struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&BIT_RD, 0);
379 struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
379 int was_detached = 0;
380 int was_noreply = 0;
381 int added = 0;
382 /* there are no limits on the number of callbacks */
383
384 /* see if it already exists, if not, create one */
385 if(!s) {
386#ifdef UNBOUND_DEBUG
387 struct rbnode_t* n;
388#endif
380 int was_detached = 0;
381 int was_noreply = 0;
382 int added = 0;
383 /* there are no limits on the number of callbacks */
384
385 /* see if it already exists, if not, create one */
386 if(!s) {
387#ifdef UNBOUND_DEBUG
388 struct rbnode_t* n;
389#endif
389 s = mesh_state_create(mesh->env, qinfo, qflags&BIT_RD, 0);
390 s = mesh_state_create(mesh->env, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
390 if(!s) {
391 return 0;
392 }
393#ifdef UNBOUND_DEBUG
394 n =
395#else
396 (void)
397#endif

--- 25 unchanged lines hidden (view full) ---

423 if(added)
424 mesh_run(mesh, s, module_event_new, NULL);
425 return 1;
426}
427
428void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
429 uint16_t qflags, time_t leeway)
430{
391 if(!s) {
392 return 0;
393 }
394#ifdef UNBOUND_DEBUG
395 n =
396#else
397 (void)
398#endif

--- 25 unchanged lines hidden (view full) ---

424 if(added)
425 mesh_run(mesh, s, module_event_new, NULL);
426 return 1;
427}
428
429void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
430 uint16_t qflags, time_t leeway)
431{
431 struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&BIT_RD, 0);
432 struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
432#ifdef UNBOUND_DEBUG
433 struct rbnode_t* n;
434#endif
435 /* already exists, and for a different purpose perhaps.
436 * if mesh_no_list, keep it that way. */
437 if(s) {
438 /* make it ignore the cache from now on */
439 if(!s->s.blacklist)
440 sock_list_insert(&s->s.blacklist, NULL, 0, s->s.region);
441 if(s->s.prefetch_leeway < leeway)
442 s->s.prefetch_leeway = leeway;
443 return;
444 }
445 if(!mesh_make_new_space(mesh, NULL)) {
446 verbose(VERB_ALGO, "Too many queries. dropped prefetch.");
447 mesh->stats_dropped ++;
448 return;
449 }
433#ifdef UNBOUND_DEBUG
434 struct rbnode_t* n;
435#endif
436 /* already exists, and for a different purpose perhaps.
437 * if mesh_no_list, keep it that way. */
438 if(s) {
439 /* make it ignore the cache from now on */
440 if(!s->s.blacklist)
441 sock_list_insert(&s->s.blacklist, NULL, 0, s->s.region);
442 if(s->s.prefetch_leeway < leeway)
443 s->s.prefetch_leeway = leeway;
444 return;
445 }
446 if(!mesh_make_new_space(mesh, NULL)) {
447 verbose(VERB_ALGO, "Too many queries. dropped prefetch.");
448 mesh->stats_dropped ++;
449 return;
450 }
450 s = mesh_state_create(mesh->env, qinfo, qflags&BIT_RD, 0);
451 s = mesh_state_create(mesh->env, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
451 if(!s) {
452 log_err("prefetch mesh_state_create: out of memory");
453 return;
454 }
455#ifdef UNBOUND_DEBUG
456 n =
457#else
458 (void)

--- 32 unchanged lines hidden (view full) ---

491 if(what == NETEVENT_CAPSFAIL)
492 event = module_event_capsfail;
493 }
494 mesh_run(mesh, e->qstate->mesh_info, event, e);
495}
496
497struct mesh_state*
498mesh_state_create(struct module_env* env, struct query_info* qinfo,
452 if(!s) {
453 log_err("prefetch mesh_state_create: out of memory");
454 return;
455 }
456#ifdef UNBOUND_DEBUG
457 n =
458#else
459 (void)

--- 32 unchanged lines hidden (view full) ---

492 if(what == NETEVENT_CAPSFAIL)
493 event = module_event_capsfail;
494 }
495 mesh_run(mesh, e->qstate->mesh_info, event, e);
496}
497
498struct mesh_state*
499mesh_state_create(struct module_env* env, struct query_info* qinfo,
499 uint16_t qflags, int prime)
500 uint16_t qflags, int prime, int valrec)
500{
501 struct regional* region = alloc_reg_obtain(env->alloc);
502 struct mesh_state* mstate;
503 int i;
504 if(!region)
505 return NULL;
506 mstate = (struct mesh_state*)regional_alloc(region,
507 sizeof(struct mesh_state));

--- 20 unchanged lines hidden (view full) ---

528 qinfo->qname_len);
529 if(!mstate->s.qinfo.qname) {
530 alloc_reg_release(env->alloc, region);
531 return NULL;
532 }
533 /* remove all weird bits from qflags */
534 mstate->s.query_flags = (qflags & (BIT_RD|BIT_CD));
535 mstate->s.is_priming = prime;
501{
502 struct regional* region = alloc_reg_obtain(env->alloc);
503 struct mesh_state* mstate;
504 int i;
505 if(!region)
506 return NULL;
507 mstate = (struct mesh_state*)regional_alloc(region,
508 sizeof(struct mesh_state));

--- 20 unchanged lines hidden (view full) ---

529 qinfo->qname_len);
530 if(!mstate->s.qinfo.qname) {
531 alloc_reg_release(env->alloc, region);
532 return NULL;
533 }
534 /* remove all weird bits from qflags */
535 mstate->s.query_flags = (qflags & (BIT_RD|BIT_CD));
536 mstate->s.is_priming = prime;
537 mstate->s.is_valrec = valrec;
536 mstate->s.reply = NULL;
537 mstate->s.region = region;
538 mstate->s.curmod = 0;
539 mstate->s.return_msg = 0;
540 mstate->s.return_rcode = LDNS_RCODE_NOERROR;
541 mstate->s.env = env;
542 mstate->s.mesh_info = mstate;
543 mstate->s.prefetch_leeway = 0;

--- 130 unchanged lines hidden (view full) ---

674 log_assert(mesh->num_detached_states +
675 mesh->num_reply_states <= mesh->all.count);
676 }
677 }
678 rbtree_init(&qstate->mesh_info->sub_set, &mesh_state_ref_compare);
679}
680
681int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
538 mstate->s.reply = NULL;
539 mstate->s.region = region;
540 mstate->s.curmod = 0;
541 mstate->s.return_msg = 0;
542 mstate->s.return_rcode = LDNS_RCODE_NOERROR;
543 mstate->s.env = env;
544 mstate->s.mesh_info = mstate;
545 mstate->s.prefetch_leeway = 0;

--- 130 unchanged lines hidden (view full) ---

676 log_assert(mesh->num_detached_states +
677 mesh->num_reply_states <= mesh->all.count);
678 }
679 }
680 rbtree_init(&qstate->mesh_info->sub_set, &mesh_state_ref_compare);
681}
682
683int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
682 uint16_t qflags, int prime, struct module_qstate** newq)
684 uint16_t qflags, int prime, int valrec, struct module_qstate** newq)
683{
684 /* find it, if not, create it */
685 struct mesh_area* mesh = qstate->env->mesh;
685{
686 /* find it, if not, create it */
687 struct mesh_area* mesh = qstate->env->mesh;
686 struct mesh_state* sub = mesh_area_find(mesh, qinfo, qflags, prime);
688 struct mesh_state* sub = mesh_area_find(mesh, qinfo, qflags, prime,
689 valrec);
687 int was_detached;
688 if(mesh_detect_cycle_found(qstate, sub)) {
689 verbose(VERB_ALGO, "attach failed, cycle detected");
690 return 0;
691 }
692 if(!sub) {
693#ifdef UNBOUND_DEBUG
694 struct rbnode_t* n;
695#endif
696 /* create a new one */
690 int was_detached;
691 if(mesh_detect_cycle_found(qstate, sub)) {
692 verbose(VERB_ALGO, "attach failed, cycle detected");
693 return 0;
694 }
695 if(!sub) {
696#ifdef UNBOUND_DEBUG
697 struct rbnode_t* n;
698#endif
699 /* create a new one */
697 sub = mesh_state_create(qstate->env, qinfo, qflags, prime);
700 sub = mesh_state_create(qstate->env, qinfo, qflags, prime,
701 valrec);
698 if(!sub) {
699 log_err("mesh_attach_sub: out of memory");
700 return 0;
701 }
702#ifdef UNBOUND_DEBUG
703 n =
704#else
705 (void)

--- 230 unchanged lines hidden (view full) ---

936 fptr_ok(fptr_whitelist_mod_inform_super(
937 mesh->mods.mod[ref->s->s.curmod]->inform_super));
938 (*mesh->mods.mod[ref->s->s.curmod]->inform_super)(&mstate->s,
939 ref->s->s.curmod, &ref->s->s);
940 }
941}
942
943struct mesh_state* mesh_area_find(struct mesh_area* mesh,
702 if(!sub) {
703 log_err("mesh_attach_sub: out of memory");
704 return 0;
705 }
706#ifdef UNBOUND_DEBUG
707 n =
708#else
709 (void)

--- 230 unchanged lines hidden (view full) ---

940 fptr_ok(fptr_whitelist_mod_inform_super(
941 mesh->mods.mod[ref->s->s.curmod]->inform_super));
942 (*mesh->mods.mod[ref->s->s.curmod]->inform_super)(&mstate->s,
943 ref->s->s.curmod, &ref->s->s);
944 }
945}
946
947struct mesh_state* mesh_area_find(struct mesh_area* mesh,
944 struct query_info* qinfo, uint16_t qflags, int prime)
948 struct query_info* qinfo, uint16_t qflags, int prime, int valrec)
945{
946 struct mesh_state key;
947 struct mesh_state* result;
948
949 key.node.key = &key;
950 key.s.is_priming = prime;
949{
950 struct mesh_state key;
951 struct mesh_state* result;
952
953 key.node.key = &key;
954 key.s.is_priming = prime;
955 key.s.is_valrec = valrec;
951 key.s.qinfo = *qinfo;
952 key.s.query_flags = qflags;
953
954 result = (struct mesh_state*)rbtree_search(&mesh->all, &key);
955 return result;
956}
957
958int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns,

--- 143 unchanged lines hidden (view full) ---

1102
1103void
1104mesh_log_list(struct mesh_area* mesh)
1105{
1106 char buf[30];
1107 struct mesh_state* m;
1108 int num = 0;
1109 RBTREE_FOR(m, struct mesh_state*, &mesh->all) {
956 key.s.qinfo = *qinfo;
957 key.s.query_flags = qflags;
958
959 result = (struct mesh_state*)rbtree_search(&mesh->all, &key);
960 return result;
961}
962
963int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns,

--- 143 unchanged lines hidden (view full) ---

1107
1108void
1109mesh_log_list(struct mesh_area* mesh)
1110{
1111 char buf[30];
1112 struct mesh_state* m;
1113 int num = 0;
1114 RBTREE_FOR(m, struct mesh_state*, &mesh->all) {
1110 snprintf(buf, sizeof(buf), "%d%s%s%s%s%s mod%d %s%s",
1115 snprintf(buf, sizeof(buf), "%d%s%s%s%s%s%s mod%d %s%s",
1111 num++, (m->s.is_priming)?"p":"", /* prime */
1116 num++, (m->s.is_priming)?"p":"", /* prime */
1117 (m->s.is_valrec)?"v":"", /* prime */
1112 (m->s.query_flags&BIT_RD)?"RD":"",
1113 (m->s.query_flags&BIT_CD)?"CD":"",
1114 (m->super_set.count==0)?"d":"", /* detached */
1115 (m->sub_set.count!=0)?"c":"", /* children */
1116 m->s.curmod, (m->reply_list)?"rep":"", /*hasreply*/
1117 (m->cb_list)?"cb":"" /* callbacks */
1118 );
1119 log_query_info(VERB_ALGO, buf, &m->s.qinfo);

--- 53 unchanged lines hidden (view full) ---

1173 /* all, including m itself allocated in qstate region */
1174 s += regional_get_mem(m->s.region);
1175 }
1176 return s;
1177}
1178
1179int
1180mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo,
1118 (m->s.query_flags&BIT_RD)?"RD":"",
1119 (m->s.query_flags&BIT_CD)?"CD":"",
1120 (m->super_set.count==0)?"d":"", /* detached */
1121 (m->sub_set.count!=0)?"c":"", /* children */
1122 m->s.curmod, (m->reply_list)?"rep":"", /*hasreply*/
1123 (m->cb_list)?"cb":"" /* callbacks */
1124 );
1125 log_query_info(VERB_ALGO, buf, &m->s.qinfo);

--- 53 unchanged lines hidden (view full) ---

1179 /* all, including m itself allocated in qstate region */
1180 s += regional_get_mem(m->s.region);
1181 }
1182 return s;
1183}
1184
1185int
1186mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo,
1181 uint16_t flags, int prime)
1187 uint16_t flags, int prime, int valrec)
1182{
1183 struct mesh_area* mesh = qstate->env->mesh;
1188{
1189 struct mesh_area* mesh = qstate->env->mesh;
1184 struct mesh_state* dep_m = mesh_area_find(mesh, qinfo, flags, prime);
1190 struct mesh_state* dep_m = mesh_area_find(mesh, qinfo, flags, prime,
1191 valrec);
1185 return mesh_detect_cycle_found(qstate, dep_m);
1186}
1187
1188void mesh_list_insert(struct mesh_state* m, struct mesh_state** fp,
1189 struct mesh_state** lp)
1190{
1191 /* insert as last element */
1192 m->prev = *lp;

--- 17 unchanged lines hidden ---
1192 return mesh_detect_cycle_found(qstate, dep_m);
1193}
1194
1195void mesh_list_insert(struct mesh_state* m, struct mesh_state** fp,
1196 struct mesh_state** lp)
1197{
1198 /* insert as last element */
1199 m->prev = *lp;

--- 17 unchanged lines hidden ---