static int request_next(struct request *req, struct sa* dst) { struct dnsrr *rr; int err = 0; rr = list_ledata(req->addrl.head); if(!rr) return -ENOENT; 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); return err; }
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 bool rr_handler(struct dnsrr *rr, void *arg) { struct http_req *req = arg; if (req->srvc >= ARRAY_SIZE(req->srvv)) return true; switch (rr->type) { case DNS_TYPE_A: sa_set_in(&req->srvv[req->srvc++], rr->rdata.a.addr, req->port); break; case DNS_TYPE_AAAA: sa_set_in6(&req->srvv[req->srvc++], rr->rdata.aaaa.addr, req->port); break; } return false; }
static void aaaa_handler(int err, const struct dnshdr *hdr, struct list *ansl, struct list *authl, struct list *addl, void *arg) { struct stun_dns *dns = arg; struct dnsrr *rr; (void)hdr; (void)authl; (void)addl; /* Find A answers */ rr = dns_rrlist_find(ansl, NULL, DNS_TYPE_AAAA, DNS_CLASS_IN, false); if (!rr) { err = err ? err : EDESTADDRREQ; goto out; } sa_set_in6(&dns->srv, rr->rdata.aaaa.addr, sa_port(&dns->srv)); DEBUG_INFO("AAAA answer: %j\n", &dns->srv); out: resolved(dns, err); }
static void srv_handler(int err, const struct dnshdr *hdr, struct list *ansl, struct list *authl, struct list *addl, void *arg) { struct stun_dns *dns = arg; struct dnsrr *rr, *arr; (void)hdr; (void)authl; dns_rrlist_sort(ansl, DNS_TYPE_SRV); /* Find SRV answers */ rr = dns_rrlist_find(ansl, NULL, DNS_TYPE_SRV, DNS_CLASS_IN, false); if (!rr) { DEBUG_INFO("no SRV entry, trying A lookup on \"%s\"\n", dns->domain); sa_set_in(&dns->srv, 0, dns->port); err = a_or_aaaa_query(dns, dns->domain); if (err) goto out; return; } DEBUG_INFO("SRV answer: %s:%u\n", rr->rdata.srv.target, rr->rdata.srv.port); /* Look for Additional information */ switch (dns->af) { case AF_INET: arr = dns_rrlist_find(addl, rr->rdata.srv.target, DNS_TYPE_A, DNS_CLASS_IN, true); if (arr) { sa_set_in(&dns->srv, arr->rdata.a.addr, rr->rdata.srv.port); DEBUG_INFO("additional A: %j\n", &dns->srv); goto out; } break; #ifdef HAVE_INET6 case AF_INET6: arr = dns_rrlist_find(addl, rr->rdata.srv.target, DNS_TYPE_AAAA, DNS_CLASS_IN, true); if (arr) { sa_set_in6(&dns->srv, arr->rdata.aaaa.addr, rr->rdata.srv.port); DEBUG_INFO("additional AAAA: %j\n", &dns->srv); goto out; } break; #endif } sa_set_in(&dns->srv, 0, rr->rdata.srv.port); err = a_or_aaaa_query(dns, rr->rdata.srv.target); if (err) { DEBUG_WARNING("SRV: A lookup failed (%m)\n", err); goto out; } DEBUG_INFO("SRV handler: doing A/AAAA lookup..\n"); return; out: resolved(dns, err); }
/* Parse one route */ static int rt_parse(const struct nlmsghdr *nlhdr, struct net_rt *rt) { struct rtmsg *rtmsg; struct rtattr *rtattr; int len; rtmsg = (struct rtmsg *)NLMSG_DATA(nlhdr); /* If the route does not belong to main routing table then return. */ if (RT_TABLE_MAIN != rtmsg->rtm_table) return EINVAL; sa_init(&rt->dst, rtmsg->rtm_family); rt->dstlen = rtmsg->rtm_dst_len; /* get the rtattr field */ rtattr = (struct rtattr *)RTM_RTA(rtmsg); len = RTM_PAYLOAD(nlhdr); for (;RTA_OK(rtattr, len); rtattr = RTA_NEXT(rtattr, len)) { switch (rtattr->rta_type) { case RTA_OIF: if_indextoname(*(int *)RTA_DATA(rtattr), rt->ifname); break; case RTA_GATEWAY: switch (rtmsg->rtm_family) { case AF_INET: sa_init(&rt->gw, AF_INET); rt->gw.u.in.sin_addr.s_addr = *(uint32_t *)RTA_DATA(rtattr); break; #ifdef HAVE_INET6 case AF_INET6: sa_set_in6(&rt->gw, RTA_DATA(rtattr), 0); break; #endif default: DEBUG_WARNING("RTA_DST: unknown family %d\n", rtmsg->rtm_family); break; } break; #if 0 case RTA_PREFSRC: rt->srcaddr = *(uint32_t *)RTA_DATA(rtattr); break; #endif case RTA_DST: switch (rtmsg->rtm_family) { case AF_INET: sa_init(&rt->dst, AF_INET); rt->dst.u.in.sin_addr.s_addr = *(uint32_t *)RTA_DATA(rtattr); break; #ifdef HAVE_INET6 case AF_INET6: sa_set_in6(&rt->dst, RTA_DATA(rtattr), 0); break; #endif default: DEBUG_WARNING("RTA_DST: unknown family %d\n", rtmsg->rtm_family); break; } break; } } return 0; }