static void query_handler(int err, const struct dnshdr *hdr, struct list *ansl, struct list *authl, struct list *addl, void *arg) { struct http_req *req = arg; (void)hdr; (void)authl; (void)addl; dns_rrlist_apply2(ansl, req->host, DNS_TYPE_A, DNS_TYPE_AAAA, DNS_CLASS_IN, true, rr_handler, req); if (req->srvc == 0) { err = err ? err : EDESTADDRREQ; goto fail; } err = req_connect(req); if (err) goto fail; return; fail: req_close(req, err, NULL); mem_deref(req); }
static void addr_handler(int err, const struct dnshdr *hdr, struct list *ansl, struct list *authl, struct list *addl, void *arg) { struct request *req = arg; int ok; (void)hdr; (void)authl; (void)addl; dns_rrlist_apply2(ansl, NULL, DNS_TYPE_A, DNS_TYPE_AAAA, DNS_CLASS_IN, false, rr_append_handler, &req->addrl); ok = request_next(req, &req->dest); mem_deref(req->dnsq); DEBUG_INFO("dns ok %d dst %j\n", ok, &req->dest); if(ok) goto fail; req->state = RESOLVED; http_send(req); return; fail: DEBUG_WARNING("cant resolve %s\n", req->host); req->err_h(-ENOTCONN, req->arg); mem_deref(req); }
static int request_next(struct sip_request *req) { struct dnsrr *rr; struct sa dst; int err; again: rr = list_ledata(req->addrl.head); if (!rr) { rr = list_ledata(req->srvl.head); if (!rr) return ENOENT; req->port = rr->rdata.srv.port; dns_rrlist_apply2(&req->cachel, rr->rdata.srv.target, DNS_TYPE_A, DNS_TYPE_AAAA, DNS_CLASS_IN, true, rr_append_handler, &req->addrl); list_unlink(&rr->le); if (req->addrl.head) { mem_deref(rr); goto again; } err = addr_lookup(req, rr->rdata.srv.target); mem_deref(rr); return err; } switch (rr->type) { case DNS_TYPE_A: sa_set_in(&dst, rr->rdata.a.addr, req->port); break; case DNS_TYPE_AAAA: sa_set_in6(&dst, rr->rdata.aaaa.addr, req->port); break; default: return EINVAL; } list_unlink(&rr->le); mem_deref(rr); err = request(req, req->tp, &dst); if (err) { if (req->addrl.head || req->srvl.head) goto again; } return err; }
static void addr_handler(int err, const struct dnshdr *hdr, struct list *ansl, struct list *authl, struct list *addl, void *arg) { struct sip_request *req = arg; (void)hdr; (void)authl; (void)addl; dns_rrlist_apply2(ansl, NULL, DNS_TYPE_A, DNS_TYPE_AAAA, DNS_CLASS_IN, false, rr_append_handler, &req->addrl); /* wait for other (A/AAAA) query to complete */ if (req->dnsq || req->dnsq2) return; if (!req->addrl.head && !req->srvl.head) { err = err ? err : EDESTADDRREQ; goto fail; } err = request_next(req); if (err) goto fail; if (!req->stateful) { req->resph = NULL; terminate(req, 0, NULL); mem_deref(req); } return; fail: terminate(req, err, NULL); mem_deref(req); }