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 --- |