+int
+vnet_dns_response_to_name (u8 * response,
+ vl_api_dns_resolve_ip_reply_t * rmp,
+ u32 * min_ttlp)
+{
+ dns_header_t *h;
+ dns_query_t *qp;
+ dns_rr_t *rr;
+ int i, limit;
+ u8 len;
+ u8 *curpos, *pos;
+ u16 flags;
+ u16 rcode;
+ u8 *name;
+ u32 ttl;
+ u8 *junk __attribute__ ((unused));
+ int name_set = 0;
+
+ h = (dns_header_t *) response;
+ flags = clib_net_to_host_u16 (h->flags);
+ rcode = flags & DNS_RCODE_MASK;
+
+ /* See if the response is OK, etc. */
+ switch (rcode)
+ {
+ default:
+ case DNS_RCODE_NO_ERROR:
+ break;
+
+ case DNS_RCODE_NAME_ERROR:
+ case DNS_RCODE_FORMAT_ERROR:
+ return VNET_API_ERROR_NAME_SERVER_NO_SUCH_NAME;
+
+ case DNS_RCODE_SERVER_FAILURE:
+ case DNS_RCODE_NOT_IMPLEMENTED:
+ case DNS_RCODE_REFUSED:
+ return VNET_API_ERROR_NAME_SERVER_NEXT_SERVER;
+ }
+
+ /* No answers? Loser... */
+ if (clib_net_to_host_u16 (h->anscount) < 1)
+ return VNET_API_ERROR_NAME_SERVER_NO_ADDRESSES;
+
+ curpos = (u8 *) (h + 1);
+
+ /* Skip the name we asked about */
+ pos = curpos;
+ len = *pos++;
+ /* Should never happen, but stil... */
+ if ((len & 0xC0) == 0xC0)
+ curpos += 2;
+ else
+ {
+ /* skip the name / label-set */
+ while (len)
+ {
+ pos += len;
+ len = *pos++;
+ }
+ curpos = pos;
+ }
+ /* Skip queries */
+ limit = clib_net_to_host_u16 (h->qdcount);
+ qp = (dns_query_t *) curpos;
+ qp += limit;
+ curpos = (u8 *) qp;
+
+ /* Parse answers */
+ limit = clib_net_to_host_u16 (h->anscount);
+
+ for (i = 0; i < limit; i++)
+ {
+ pos = curpos;
+
+ /* Expect pointer chases in the answer section... */
+ if ((pos[0] & 0xC0) == 0xC0)
+ curpos += 2;
+ else
+ {
+ len = *pos++;
+ while (len)
+ {
+ if ((pos[0] & 0xC0) == 0xC0)
+ {
+ curpos = pos + 2;
+ goto curpos_set;
+ }
+ pos += len;
+ len = *pos++;
+ }
+ curpos = pos;
+ }
+
+ curpos_set:
+ rr = (dns_rr_t *) curpos;
+
+ switch (clib_net_to_host_u16 (rr->type))
+ {
+ case DNS_TYPE_PTR:
+ name = labels_to_name (rr->rdata, response, &junk);
+ memcpy (rmp->name, name, vec_len (name));
+ ttl = clib_net_to_host_u32 (rr->ttl);
+ if (*min_ttlp)
+ *min_ttlp = ttl;
+ rmp->name[vec_len (name)] = 0;
+ name_set = 1;
+ break;
+ default:
+ break;
+ }
+ /* Might as well stop ASAP */
+ if (name_set == 1)
+ break;
+ curpos += sizeof (*rr) + clib_net_to_host_u16 (rr->rdlength);
+ }
+
+ if (name_set == 0)
+ return VNET_API_ERROR_NAME_SERVER_NO_SUCH_NAME;
+ return 0;
+}
+