1 /*- 2 * Copyright (c) 2012 Baptiste Daroussin <bapt@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification, immediately at the beginning of the file. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <stdlib.h> 31 #include <string.h> 32 #include <netinet/in.h> 33 #include <resolv.h> 34 35 #include "dns_utils.h" 36 37 typedef union { 38 HEADER hdr; 39 unsigned char buf[1024]; 40 } dns_query; 41 42 struct dns_srvinfo * 43 dns_getsrvinfo(const char *zone) 44 { 45 struct dns_srvinfo **res, *first; 46 unsigned char *end, *p; 47 char host[MAXHOSTNAMELEN]; 48 dns_query q; 49 int len, qdcount, ancount, n, i; 50 unsigned int type, class, ttl, priority, weight, port; 51 52 if ((len = res_query(zone, C_IN, T_SRV, q.buf, sizeof(q.buf))) == -1 || 53 len < (int)sizeof(HEADER)) 54 return (NULL); 55 56 qdcount = ntohs(q.hdr.qdcount); 57 ancount = ntohs(q.hdr.ancount); 58 59 end = q.buf + len; 60 p = q.buf + sizeof(HEADER); 61 62 while(qdcount > 0 && p < end) { 63 qdcount--; 64 if((len = dn_expand(q.buf, end, p, host, MAXHOSTNAMELEN)) < 0) 65 return (NULL); 66 p += len + NS_QFIXEDSZ; 67 } 68 69 res = calloc(ancount, sizeof(struct dns_srvinfo *)); 70 if (res == NULL) 71 return (NULL); 72 73 n = 0; 74 while (ancount > 0 && p < end) { 75 ancount--; 76 len = dn_expand(q.buf, end, p, host, MAXHOSTNAMELEN); 77 if (len < 0) { 78 for (i = 0; i < n; i++) 79 free(res[i]); 80 free(res); 81 return NULL; 82 } 83 84 p += len; 85 86 NS_GET16(type, p); 87 NS_GET16(class, p); 88 NS_GET32(ttl, p); 89 NS_GET16(len, p); 90 91 if (type != T_SRV) { 92 p += len; 93 continue; 94 } 95 96 NS_GET16(priority, p); 97 NS_GET16(weight, p); 98 NS_GET16(port, p); 99 100 len = dn_expand(q.buf, end, p, host, MAXHOSTNAMELEN); 101 if (len < 0) { 102 for (i = 0; i < n; i++) 103 free(res[i]); 104 free(res); 105 return (NULL); 106 } 107 108 res[n] = malloc(sizeof(struct dns_srvinfo)); 109 if (res[n] == NULL) { 110 for (i = 0; i < n; i++) 111 free(res[i]); 112 free(res); 113 return (NULL); 114 } 115 res[n]->type = type; 116 res[n]->class = class; 117 res[n]->ttl = ttl; 118 res[n]->priority = priority; 119 res[n]->weight = weight; 120 res[n]->port = port; 121 res[n]->next = NULL; 122 strlcpy(res[n]->host, host, MAXHOSTNAMELEN); 123 124 p += len; 125 n++; 126 } 127 128 for (i = 0; i < n - 1; i++) 129 res[i]->next = res[i + 1]; 130 131 first = res[0]; 132 free(res); 133 134 return (first); 135 } 136