/** * @return 成功した場合は NETDB_SUCCESS. */ static int DnsResolver_lookupTxtData(DnsResolver *self, int rrtype, const char *domain, DnsTxtResponse **resp) { int query_stat = DnsResolver_query(self, domain, rrtype); if (NETDB_SUCCESS != query_stat) { return query_stat; } // end if size_t msg_count = ns_msg_count(self->msghanlde, ns_s_an); DnsTxtResponse *respobj = (DnsTxtResponse *) malloc(sizeof(DnsTxtResponse) + msg_count * sizeof(char *)); if (NULL == respobj) { return DnsResolver_setError(self, NETDB_INTERNAL); } // end if memset(respobj, 0, sizeof(DnsTxtResponse) + msg_count * sizeof(char *)); respobj->num = 0; for (size_t n = 0; n < msg_count; ++n) { ns_rr rr; int parse_stat = ns_parserr(&self->msghanlde, ns_s_an, n, &rr); if (0 != parse_stat) { goto formerr; } // end if if (ns_t_txt != ns_rr_type(rr)) { continue; } // end if respobj->data[respobj->num] = (char *) malloc(ns_rr_rdlen(rr)); // RDLEN を越えることはない. if (NULL == respobj->data[respobj->num]) { goto noresource; } // end if const unsigned char *rdata = ns_rr_rdata(rr); const unsigned char *rdata_tail = ns_rr_rdata(rr) + ns_rr_rdlen(rr); char *bufp = respobj->data[respobj->num]; while (rdata < rdata_tail) { // 長さフィールドが RDLEN の中に収まっているか確認する if (rdata_tail < rdata + (*rdata) + 1) { free(respobj->data[respobj->num]); goto formerr; } // end if memcpy(bufp, rdata + 1, *rdata); bufp += (size_t) *rdata; rdata += (size_t) *rdata + 1; } // end while *bufp = '\0'; // 扱いやすいように NULL 終端させる ++(respobj->num); } // end for if (0 == respobj->num) { goto formerr; } // end if *resp = respobj; return NETDB_SUCCESS; formerr: DnsTxtResponse_free(respobj); return DnsResolver_setError(self, NO_RECOVERY); noresource: DnsTxtResponse_free(respobj); return DnsResolver_setError(self, NETDB_INTERNAL); } // end function : DnsResolver_lookupTxtData
static void test_res_fake_a_query_case_insensitive(void **state) { int rv; struct __res_state dnsstate; unsigned char answer[ANSIZE]; char addr[INET_ADDRSTRLEN]; ns_msg handle; ns_rr rr; /* expanded resource record */ (void) state; /* unused */ memset(&dnsstate, 0, sizeof(struct __res_state)); rv = res_ninit(&dnsstate); assert_int_equal(rv, 0); rv = res_nquery(&dnsstate, "CWRAP.ORG", ns_c_in, ns_t_a, answer, sizeof(answer)); assert_in_range(rv, 1, 100); ns_initparse(answer, sizeof(answer), &handle); /* The query must finish w/o an error, have one answer and the answer * must be a parseable RR of type A and have the address that our * fake hosts file contains. Case does not matter. */ assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror); assert_int_equal(ns_msg_count(handle, ns_s_an), 1); assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0); assert_int_equal(ns_rr_type(rr), ns_t_a); assert_non_null(inet_ntop(AF_INET, ns_rr_rdata(rr), addr, sizeof(addr))); assert_string_equal(addr, "127.0.0.21"); res_nclose(&dnsstate); }
static int app_parse_txt(radiodns_app_t *app, ns_msg handle, ns_rr rr, char *dnbuf) { const unsigned char *p, *start; unsigned char l; int rrlen; (void) handle; p = start = ns_rr_rdata(rr); rrlen = ns_rr_rdlen(rr); while(p < start + rrlen) { l = *p; p++; if(p + l > start + rrlen) { break; } memcpy(dnbuf, p, l); dnbuf[l] = 0; app_parse_params(app, dnbuf); p += l; } return 0; }
KDCENTRY* krb_locate_kdc(rdpSettings* settings) { #ifdef WITH_RESOLV char *qname; int reslen, i; unsigned char response[4096]; char kdc_host[4096]; unsigned char* temp; KDCENTRY* head; KDCENTRY* kdcentry; KDCENTRY* srvans; ns_msg handle; ns_rr rr; head = kdcentry = NULL; if (get_krb_realm(settings)) return NULL; if (settings->kerberos_kdc) { srvans = xnew(KDCENTRY); srvans->kdchost = xstrdup(settings->kerberos_kdc); srvans->port = 88; return srvans; } qname = get_dns_queryname(settings->kerberos_realm, "_tcp."); if ((reslen = res_query(qname, ns_c_in, ns_t_srv, response, sizeof(response))) < 0) return NULL; ns_initparse(response, reslen, &handle); for (i = 0;i < ns_msg_count(handle, ns_s_an);i++) { ns_parserr(&handle, ns_s_an, i, &rr); srvans = xnew(KDCENTRY); temp = (unsigned char*)ns_rr_rdata(rr); GETUINT16(temp, &(srvans->priority)); GETUINT16(temp, &(srvans->weight)); GETUINT16(temp, &(srvans->port)); if (ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), temp, (char*)kdc_host, sizeof(kdc_host)) < 0) srvans->kdchost = xstrdup((const char*)temp); else srvans->kdchost = xstrdup(kdc_host); if (head == NULL || head->priority > srvans->priority) { srvans->next = head; head = srvans; } else { for (kdcentry = head;kdcentry->next != NULL && kdcentry->next->priority < srvans->priority;kdcentry = kdcentry->next); srvans->next = kdcentry->next; kdcentry->next = srvans; } } return head; #else return NULL; #endif }
static int should_filter_query(ns_msg msg, struct in_addr dns_addr) { ns_rr rr; int rrnum, rrmax; void *r; // TODO cache result for each dns server int dns_is_chn = chnroute_file && (dns_servers_len > 1) && test_ip_in_list(dns_addr, &chnroute_list); rrmax = ns_msg_count(msg, ns_s_an); if (rrmax == 0) return -1; for (rrnum = 0; rrnum < rrmax; rrnum++) { if (ns_parserr(&msg, ns_s_an, rrnum, &rr)) { ERR("ns_parserr"); return 0; } u_int type; const u_char *rd; type = ns_rr_type(rr); rd = ns_rr_rdata(rr); if (type == ns_t_a) { if (verbose) printf("%s, ", inet_ntoa(*(struct in_addr *)rd)); r = bsearch(rd, ip_list.ips, ip_list.entries, sizeof(struct in_addr), cmp_in_addr); if (r) return 1; if (chnroute_file && dns_is_chn) { // filter DNS result from chn dns if result is outside chn if (!test_ip_in_list(*(struct in_addr *)rd, &chnroute_list)) return 1; } } } return 0; }
static void parse_answer_section(ns_msg *msg) { int rrnum, rrmax; ns_rr rr; uint16_t prio, weight, port, len; const unsigned char *rdata; char *tname; rrmax = ns_msg_count(*msg, ns_s_an); for (rrnum = 0; rrnum < rrmax; rrnum++) { if (ns_parserr(msg, ns_s_an, rrnum, &rr)) { perror("ns_parserr"); exit(EXIT_FAILURE); } if (ns_rr_type(rr) == ns_t_srv) { len = ns_rr_rdlen(rr); rdata = ns_rr_rdata(rr); if (len > 3U * NS_INT16SZ) { NS_GET16(prio, rdata); NS_GET16(weight, rdata); NS_GET16(port, rdata); len -= 3U * NS_INT16SZ; tname = target_name(rdata); insert_tuple(tname, prio, weight, port); } } } }
static void test_res_fake_aaaa_query(void **state) { int rv; struct __res_state dnsstate; unsigned char answer[ANSIZE]; char addr[INET6_ADDRSTRLEN]; ns_msg handle; ns_rr rr; /* expanded resource record */ (void) state; /* unused */ memset(&dnsstate, 0, sizeof(struct __res_state)); rv = res_ninit(&dnsstate); assert_int_equal(rv, 0); rv = res_nquery(&dnsstate, "cwrap6.org", ns_c_in, ns_t_aaaa, answer, sizeof(answer)); assert_in_range(rv, 1, 100); ns_initparse(answer, sizeof(answer), &handle); /* The query must finish w/o an error, have one answer and the answer * must be a parseable RR of type AAAA and have the address that our * fake hosts file contains */ assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror); assert_int_equal(ns_msg_count(handle, ns_s_an), 1); assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0); assert_int_equal(ns_rr_type(rr), ns_t_aaaa); assert_non_null(inet_ntop(AF_INET6, ns_rr_rdata(rr), addr, sizeof(addr))); assert_string_equal(addr, "2a00:1450:4013:c01::63"); }
/*% * Convert an RR to presentation format. * * return: *\li Number of characters written to buf, or -1 (check errno). */ int ns_sprintrr(const ns_msg* handle, const ns_rr* rr, const char* name_ctx, const char* origin, char* buf, size_t buflen) { int n; n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle), ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr), ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr), name_ctx, origin, buf, buflen); return (n); }
static void test_res_fake_srv_query(void **state) { int rv; struct __res_state dnsstate; unsigned char answer[ANSIZE]; ns_msg handle; ns_rr rr; /* expanded resource record */ const uint8_t *rrdata; int prio; int weight; int port; char hostname[MAXDNAME]; (void) state; /* unused */ memset(&dnsstate, 0, sizeof(struct __res_state)); rv = res_ninit(&dnsstate); assert_int_equal(rv, 0); rv = res_nquery(&dnsstate, "_ldap._tcp.cwrap.org", ns_c_in, ns_t_srv, answer, sizeof(answer)); assert_in_range(rv, 1, 100); ns_initparse(answer, sizeof(answer), &handle); /* * The query must finish w/o an error, have one answer and the answer * must be a parseable RR of type SRV and have the priority, weight, * port and hostname as in the fake hosts file */ assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror); assert_int_equal(ns_msg_count(handle, ns_s_an), 1); assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0); assert_int_equal(ns_rr_type(rr), ns_t_srv); rrdata = ns_rr_rdata(rr); NS_GET16(prio, rrdata); NS_GET16(weight, rrdata); NS_GET16(port, rrdata); rv = ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), rrdata, hostname, MAXDNAME); assert_int_not_equal(rv, -1); assert_int_equal(prio, 1); assert_int_equal(weight, 5); assert_int_equal(port, 389); assert_string_equal(hostname, "ldap.cwrap.org"); }
static JSBool parse_name(JSContext *cx, JSObject *robj, const ns_msg *hdl, const ns_rr *rr) { char name[MAXDNAME]; JSString *str; const unsigned char *base = ns_msg_base(*hdl), *end = ns_msg_end(*hdl); if (ns_name_uncompress(base, end, ns_rr_rdata(*rr), name, sizeof(name)) < 0) return JS_TRUE; str = JS_NewStringCopyZ(cx, name); if (!str) return JS_RetErrno(cx, ENOMEM); if (!JS_DefineProperty(cx, robj, "data", STRING_TO_JSVAL(str), NULL, NULL, JSPROP_ENUMERATE)) return JS_RetErrno(cx, ENOMEM); return JS_TRUE; }
int get_krb_realm(rdpSettings* settings) { #ifdef WITH_RESOLV char* s; char* queryname; int reslen; unsigned char response[2048]; char ns_realm[2048]; ns_msg handle; ns_rr rr; s = settings->hostname; if (settings->kerberos_realm) return 0; do { queryname = get_dns_queryname(s, NULL); if ((reslen = res_query(queryname, ns_c_in, ns_t_txt, response, sizeof(response)))) { ns_initparse(response, reslen, &handle); ns_parserr(&handle, ns_s_an, 0, &rr); if (ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), ns_rr_rdata(rr), (char*)ns_realm, sizeof(ns_realm)) < 0) goto end; else settings->kerberos_realm = xstrdup(ns_realm); xfree(queryname); return 0; } end: xfree(queryname); for (;*s != '.' && *s != '\0';s++); if (*s != '\0') s++; } while (*s != '\0'); s = settings->hostname; for (;*s != '.';s++); s++; settings->kerberos_realm = xstrdup(s); #endif return 0; }
char* getMailserver(const char* domain) { int len; char answer[NS_PACKETSZ]; char *mailserver = malloc(NS_PACKETSZ); ns_msg msg; ns_rr rr; if(res_init() == -1) { return NULL; } len = res_query(domain,C_ANY,T_MX,answer,NS_PACKETSZ); if(len == -1) { return NULL; } /* return first MX record */ ns_initparse(answer,len,&msg); ns_parserr(&msg,ns_s_an,0,&rr); dn_expand(ns_msg_base(msg),ns_msg_base(msg)+ns_msg_size(msg),ns_rr_rdata(rr)+NS_INT16SZ,mailserver,NS_PACKETSZ); return mailserver; }
static JSBool parse_t_a(JSContext *cx, JSObject *robj, const ns_msg *hdl, const ns_rr *rr) { char addr[16]; JSString *str; if (ns_rr_rdlen(*rr) != 4) return JS_TRUE; if (!inet_ntop(AF_INET, ns_rr_rdata(*rr), addr, sizeof(addr))) return JS_TRUE; str = JS_NewStringCopyZ(cx, addr); if (!str) return JS_RetErrno(cx, ENOMEM); if (!JS_DefineProperty(cx, robj, "data", STRING_TO_JSVAL(str), NULL, NULL, JSPROP_ENUMERATE)) return JS_RetErrno(cx, ENOMEM); return JS_TRUE; }
int DnsResolver_lookupAaaa(DnsResolver *self, const char *domain, DnsAaaaResponse **resp) { int query_stat = DnsResolver_query(self, domain, ns_t_aaaa); if (NETDB_SUCCESS != query_stat) { return query_stat; } // end if size_t msg_count = ns_msg_count(self->msghanlde, ns_s_an); DnsAaaaResponse *respobj = (DnsAaaaResponse *) malloc(sizeof(DnsAaaaResponse) + msg_count * sizeof(struct in6_addr)); if (NULL == respobj) { return DnsResolver_setError(self, NETDB_INTERNAL); } // end if memset(respobj, 0, sizeof(DnsAaaaResponse) + msg_count * sizeof(struct in6_addr)); respobj->num = 0; for (size_t n = 0; n < msg_count; ++n) { ns_rr rr; int parse_stat = ns_parserr(&self->msghanlde, ns_s_an, n, &rr); if (0 != parse_stat) { goto formerr; } // end if if (ns_t_aaaa != ns_rr_type(rr)) { continue; } // end if if (NS_IN6ADDRSZ != ns_rr_rdlen(rr)) { goto formerr; } // end if memcpy(&(respobj->addr[respobj->num]), ns_rr_rdata(rr), NS_IN6ADDRSZ); ++(respobj->num); } // end for if (0 == respobj->num) { goto formerr; } // end if *resp = respobj; return NETDB_SUCCESS; formerr: DnsAaaaResponse_free(respobj); return DnsResolver_setError(self, NO_RECOVERY); } // end function : DnsResolver_lookupAaaa
/* * krb5int_dns_nextans - get next matching answer record * * Sets pp to NULL if no more records. Returns -1 on error, 0 on * success. */ int krb5int_dns_nextans(struct krb5int_dns_state *ds, const unsigned char **pp, int *lenp) { int len; ns_rr rr; *pp = NULL; *lenp = 0; while (ds->cur_ans < ns_msg_count(ds->msg, ns_s_an)) { len = ns_parserr(&ds->msg, ns_s_an, ds->cur_ans, &rr); if (len < 0) return -1; ds->cur_ans++; if (ds->nclass == (int)ns_rr_class(rr) && ds->ntype == (int)ns_rr_type(rr)) { *pp = ns_rr_rdata(rr); *lenp = ns_rr_rdlen(rr); return 0; } } return 0; }
/* Initialize a "newmsg" object by copying an existing parsed message. */ int ns_newmsg_copy(ns_newmsg *handle, ns_msg *msg) { ns_flag flag; ns_sect sect; ns_newmsg_id(handle, ns_msg_id(*msg)); for (flag = ns_f_qr; flag < ns_f_max; flag++) ns_newmsg_flag(handle, flag, ns_msg_getflag(*msg, flag)); for (sect = ns_s_qd; sect < ns_s_max; sect++) { int i, count; count = ns_msg_count(*msg, sect); for (i = 0; i < count; i++) { ns_rr2 rr; int x; if (ns_parserr2(msg, sect, i, &rr) < 0) return (-1); if (sect == ns_s_qd) x = ns_newmsg_q(handle, ns_rr_nname(rr), ns_rr_type(rr), ns_rr_class(rr)); else x = ns_newmsg_rr(handle, sect, ns_rr_nname(rr), ns_rr_type(rr), ns_rr_class(rr), ns_rr_ttl(rr), ns_rr_rdlen(rr), ns_rr_rdata(rr)); if (x < 0) return (-1); } } return (0); }
static int app_parse_srv(radiodns_app_t *app, ns_msg handle, ns_rr rr, char *dnbuf, radiodns_srv_t *srv) { const unsigned char *rdata; (void) app; rdata = ns_rr_rdata(rr); srv->priority = ns_get16(rdata); rdata += NS_INT16SZ; srv->weight = ns_get16(rdata); rdata += NS_INT16SZ; srv->port = ns_get16(rdata); rdata += NS_INT16SZ; dn_expand(ns_msg_base(handle), ns_msg_base(handle) + ns_msg_size(handle), rdata, dnbuf, MAXDNAME); if(!(srv->target = strdup(dnbuf))) { return -2; } return 0; }
static int app_follow_ptr(radiodns_app_t *app, unsigned char *abuf, ns_msg phandle, ns_rr prr) { char dnbuf[MAXDNAME + 1], dbuf[4]; char *d, *p, *endp; ns_msg handle; ns_rr rr; int c, len, r; dn_expand(ns_msg_base(phandle), ns_msg_base(phandle) + ns_msg_size(phandle), ns_rr_rdata(prr), dnbuf, sizeof(dnbuf)); if(!(app->name = (char *) calloc(1, strlen(dnbuf)))) { return -2; } d = app->name; p = dnbuf; while(*p && *p != '.') { if(*p == '\\' && isdigit(p[1]) && isdigit(p[2]) && isdigit(p[3])) { dbuf[0] = p[1]; dbuf[1] = p[2]; dbuf[2] = p[3]; dbuf[3] = 0; c = strtol(dbuf, NULL, 10); *d = c; d++; p += 4; continue; } else if(*p == '\\' && p[1]) { /* Skip the backslash, allowing it to escape the '.' */ p++; } *d = *p; d++; p++; } *d = 0; if(0 >= (len = res_query(dnbuf, ns_c_in, ns_t_any, abuf, RDNS_ANSWERBUFLEN))) { return -1; } if(0 > ns_initparse(abuf, len, &handle)) { return -1; } if(0 > (len = ns_msg_count(handle, ns_s_an))) { return -1; } if(!(app->srv = (radiodns_srv_t *) calloc(len, sizeof(radiodns_srv_t)))) { return -2; } for(c = 0; c < len; c++) { if(ns_parserr(&handle, ns_s_an, c, &rr)) { continue; } if(ns_rr_class(rr) != ns_c_in) { continue; } if(ns_rr_type(rr) == ns_t_txt) { app_parse_txt(app, handle, rr, dnbuf); } if(ns_rr_type(rr) == ns_t_srv) { r = app_parse_srv(app, handle, rr, dnbuf, &(app->srv[app->nsrv])); if(r == 0) { app->nsrv++; } else { return r; } } } if(app->nsrv) { return 0; } return -1; }
int DnsResolver_lookupMx(DnsResolver *self, const char *domain, DnsMxResponse **resp) { int query_stat = DnsResolver_query(self, domain, ns_t_mx); if (NETDB_SUCCESS != query_stat) { return query_stat; } // end if size_t msg_count = ns_msg_count(self->msghanlde, ns_s_an); DnsMxResponse *respobj = (DnsMxResponse *) malloc(sizeof(DnsMxResponse) + msg_count * sizeof(struct mxentry *)); if (NULL == respobj) { return DnsResolver_setError(self, NETDB_INTERNAL); } // end if memset(respobj, 0, sizeof(DnsMxResponse) + msg_count * sizeof(struct mxentry *)); respobj->num = 0; for (size_t n = 0; n < msg_count; ++n) { ns_rr rr; int parse_stat = ns_parserr(&self->msghanlde, ns_s_an, n, &rr); if (0 != parse_stat) { goto formerr; } // end if if (ns_t_mx != ns_rr_type(rr)) { continue; } // end if const unsigned char *rdata = ns_rr_rdata(rr); if (ns_rr_rdlen(rr) < NS_INT16SZ) { goto formerr; } // end if int preference = ns_get16(rdata); rdata += NS_INT16SZ; // NOTE: NS_MAXDNAME で十分なのかイマイチ確証が持てないが, bind8 の dig コマンドの実装でもこの値を使っていたのでいいのではないか. char dnamebuf[NS_MAXDNAME]; int dnamelen = ns_name_uncompress(self->msgbuf, self->msgbuf + self->msglen, rdata, dnamebuf, sizeof(dnamebuf)); if (NS_INT16SZ + dnamelen != ns_rr_rdlen(rr)) { goto formerr; } // end if // TODO: dnamebuf は NULL 終端が保証されているのか? size_t domainlen = strlen(dnamebuf); respobj->exchange[respobj->num] = (struct mxentry *) malloc(sizeof(struct mxentry) + sizeof(char[domainlen + 1])); if (NULL == respobj->exchange[respobj->num]) { goto noresource; } // end if respobj->exchange[respobj->num]->preference = preference; if (domainlen + 1 <= strlcpy(respobj->exchange[respobj->num]->domain, dnamebuf, domainlen + 1)) { abort(); } // end if ++(respobj->num); } // end for if (0 == respobj->num) { goto formerr; } // end if *resp = respobj; return NETDB_SUCCESS; formerr: DnsMxResponse_free(respobj); return DnsResolver_setError(self, NO_RECOVERY); noresource: DnsMxResponse_free(respobj); return DnsResolver_setError(self, NETDB_INTERNAL); } // end function : DnsResolver_lookupMx
/* * Test the case of a SRV record query where the * fake hosts file entry is minimal in the sense * that it omits the priority and weight entries. * The server then fills in some default values. */ static void test_res_fake_srv_query_minimal(void **state) { int rv; struct __res_state dnsstate; unsigned char answer[ANSIZE]; ns_msg handle; ns_rr rr; /* expanded resource record */ const uint8_t *rrdata; int prio; int weight; int port; char hostname[MAXDNAME]; char addr[INET_ADDRSTRLEN]; (void) state; /* unused */ memset(&dnsstate, 0, sizeof(struct __res_state)); rv = res_ninit(&dnsstate); assert_int_equal(rv, 0); rv = res_nquery(&dnsstate, "_krb5._tcp.cwrap.org", ns_c_in, ns_t_srv, answer, sizeof(answer)); assert_in_range(rv, 1, 256); ns_initparse(answer, sizeof(answer), &handle); /* * The query must finish w/o an error, have one answer and the answer * must be a parseable RR of type SRV and have the priority, weight, * port and hostname as in the fake hosts file */ assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror); assert_int_equal(ns_msg_count(handle, ns_s_an), 1); assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0); assert_int_equal(ns_rr_type(rr), ns_t_srv); rrdata = ns_rr_rdata(rr); NS_GET16(prio, rrdata); NS_GET16(weight, rrdata); NS_GET16(port, rrdata); rv = ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), rrdata, hostname, MAXDNAME); assert_int_not_equal(rv, -1); assert_int_equal(prio, 1); assert_int_equal(weight, 100); assert_int_equal(port, 88); assert_string_equal(hostname, "krb5.cwrap.org"); /* The additional section contains the A record of krb5.cwrap.org */ assert_int_equal(ns_msg_count(handle, ns_s_ar), 1); assert_int_equal(ns_parserr(&handle, ns_s_ar, 0, &rr), 0); assert_int_equal(ns_rr_type(rr), ns_t_a); assert_string_equal(ns_rr_name(rr), "krb5.cwrap.org"); assert_non_null(inet_ntop(AF_INET, ns_rr_rdata(rr), addr, sizeof(addr))); assert_string_equal(addr, "127.0.0.23"); }
int dns_get_mx_list(const char *host, int port, struct mx_hostentry **he, int no_mx) { char outname[MAXDNAME]; ns_msg msg; ns_rr rr; const char *searchhost; const unsigned char *cp; unsigned char *ans; struct mx_hostentry *hosts = NULL; size_t nhosts = 0; size_t anssz; int pref; int cname_recurse; int err; int i; res_init(); searchhost = host; cname_recurse = 0; anssz = 65536; ans = malloc(anssz); if (ans == NULL) return (1); if (no_mx) goto out; repeat: err = res_search(searchhost, ns_c_in, ns_t_mx, ans, anssz); if (err < 0) { switch (h_errno) { case NO_DATA: /* * Host exists, but no MX (or CNAME) entry. * Not an error, use host name instead. */ goto out; case TRY_AGAIN: /* transient error */ goto transerr; case NO_RECOVERY: case HOST_NOT_FOUND: default: errno = ENOENT; goto err; } } if (!ns_initparse(ans, anssz, &msg)) goto transerr; switch (ns_msg_getflag(msg, ns_f_rcode)) { case ns_r_noerror: break; case ns_r_nxdomain: goto err; default: goto transerr; } for (i = 0; i < ns_msg_count(msg, ns_s_an); i++) { if (ns_parserr(&msg, ns_s_an, i, &rr)) goto transerr; cp = ns_rr_rdata(rr); switch (ns_rr_type(rr)) { case ns_t_mx: pref = ns_get16(cp); cp += 2; err = ns_name_uncompress(ns_msg_base(msg), ns_msg_end(msg), cp, outname, sizeof(outname)); if (err < 0) goto transerr; add_host(pref, outname, port, &hosts, &nhosts); break; case ns_t_cname: err = ns_name_uncompress(ns_msg_base(msg), ns_msg_end(msg), cp, outname, sizeof(outname)); if (err < 0) goto transerr; /* Prevent a CNAME loop */ if (cname_recurse++ > 10) goto err; searchhost = outname; goto repeat; default: break; } } out: err = 0; if (0) { transerr: if (nhosts == 0) err = 1; } if (0) { err: err = -1; } free(ans); if (!err) { /* * If we didn't find any MX, use the hostname instead. */ if (nhosts == 0) add_host(0, searchhost, port, &hosts, &nhosts); qsort(hosts, nhosts, sizeof(*hosts), sort_pref); } if (nhosts > 0) { /* terminate list */ *hosts[nhosts].host = 0; } else { if (hosts != NULL) free(hosts); hosts = NULL; } *he = hosts; return (err); free(ans); if (hosts != NULL) free(hosts); return (err); }
static void afsdb_hosts_to_addrs(char *vllist[], int *vlsnum, ns_msg handle, ns_sect section, unsigned mask, unsigned long *_ttl) { int rrnum; ns_rr rr; int subtype, i, ret; unsigned int ttl = UINT_MAX, rr_ttl; debug("AFSDB RR count is %d", ns_msg_count(handle, section)); /* Look at all the resource records in this section. */ for (rrnum = 0; rrnum < ns_msg_count(handle, section); rrnum++) { /* Expand the resource record number rrnum into rr. */ if (ns_parserr(&handle, section, rrnum, &rr)) { _error("ns_parserr failed : %m"); continue; } /* We're only interested in AFSDB records */ if (ns_rr_type(rr) == ns_t_afsdb) { vllist[*vlsnum] = malloc(MAXDNAME); if (!vllist[*vlsnum]) error("Out of memory"); subtype = ns_get16(ns_rr_rdata(rr)); /* Expand the name server's domain name */ if (ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), ns_rr_rdata(rr) + 2, vllist[*vlsnum], MAXDNAME) < 0) error("ns_name_uncompress failed"); rr_ttl = ns_rr_ttl(rr); if (ttl > rr_ttl) ttl = rr_ttl; /* Check the domain name we've just unpacked and add it to * the list of VL servers if it is not a duplicate. * If it is a duplicate, just ignore it. */ for (i = 0; i < *vlsnum; i++) if (strcasecmp(vllist[i], vllist[*vlsnum]) == 0) goto next_one; /* Turn the hostname into IP addresses */ ret = dns_resolver(vllist[*vlsnum], mask); if (ret) { debug("AFSDB RR can't resolve." "subtype:%d, server name:%s, netmask:%u", subtype, vllist[*vlsnum], mask); goto next_one; } info("AFSDB RR subtype:%d, server name:%s, ip:%*.*s, ttl:%u", subtype, vllist[*vlsnum], (int)payload[payload_index - 1].iov_len, (int)payload[payload_index - 1].iov_len, (char *)payload[payload_index - 1].iov_base, ttl); /* prepare for the next record */ *vlsnum += 1; continue; next_one: free(vllist[*vlsnum]); } } *_ttl = ttl; info("ttl: %u", ttl); }
static void do_section(const res_state statp, ns_msg *handle, ns_sect section, int pflag, FILE *file) { int n, sflag, rrnum; static int buflen = 2048; char *buf; ns_opcode opcode; ns_rr rr; /* * Print answer records. */ sflag = (statp->pfcode & pflag); if (statp->pfcode && !sflag) return; buf = malloc(buflen); if (buf == NULL) { fprintf(file, ";; memory allocation failure\n"); return; } opcode = (ns_opcode) ns_msg_getflag(*handle, ns_f_opcode); rrnum = 0; for (;;) { if (ns_parserr(handle, section, rrnum, &rr)) { if (errno != ENODEV) fprintf(file, ";; ns_parserr: %s\n", strerror(errno)); else if (rrnum > 0 && sflag != 0 && (statp->pfcode & RES_PRF_HEAD1)) putc('\n', file); goto cleanup; } if (rrnum == 0 && sflag != 0 && (statp->pfcode & RES_PRF_HEAD1)) fprintf(file, ";; %s SECTION:\n", p_section(section, opcode)); if (section == ns_s_qd) fprintf(file, ";;\t%s, type = %s, class = %s\n", ns_rr_name(rr), p_type(ns_rr_type(rr)), p_class(ns_rr_class(rr))); else if (section == ns_s_ar && ns_rr_type(rr) == ns_t_opt) { u_int16_t optcode, optlen, rdatalen = ns_rr_rdlen(rr); u_int32_t ttl = ns_rr_ttl(rr); fprintf(file, "; EDNS: version: %u, udp=%u, flags=%04x\n", (ttl>>16)&0xff, ns_rr_class(rr), ttl&0xffff); while (rdatalen >= 4) { const u_char *cp = ns_rr_rdata(rr); int i; GETSHORT(optcode, cp); GETSHORT(optlen, cp); if (optcode == NS_OPT_NSID) { fputs("; NSID: ", file); if (optlen == 0) { fputs("; NSID\n", file); } else { fputs("; NSID: ", file); for (i = 0; i < optlen; i++) fprintf(file, "%02x ", cp[i]); fputs(" (",file); for (i = 0; i < optlen; i++) fprintf(file, "%c", isprint(cp[i])? cp[i] : '.'); fputs(")\n", file); } } else { if (optlen == 0) { fprintf(file, "; OPT=%u\n", optcode); } else { fprintf(file, "; OPT=%u: ", optcode); for (i = 0; i < optlen; i++) fprintf(file, "%02x ", cp[i]); fputs(" (",file); for (i = 0; i < optlen; i++) fprintf(file, "%c", isprint(cp[i]) ? cp[i] : '.'); fputs(")\n", file); } } rdatalen -= 4 + optlen; } } else {
int DnsResolver_lookupPtr(DnsResolver *self, int af, const void *addr, DnsPtrResponse **resp) { // IPv6 の逆引きエントリ名生成に十分な長さのバッファを確保する. char domain[DNS_IP6_REVENT_MAXLEN]; switch (af) { case AF_INET: if (!DnsResolver_expandReverseEntry4(addr, domain, sizeof(domain))) { abort(); } // end if break; case AF_INET6: if (!DnsResolver_expandReverseEntry6(addr, domain, sizeof(domain))) { abort(); } // end if break; default: errno = EAFNOSUPPORT; return NETDB_INTERNAL; } // end if int query_stat = DnsResolver_query(self, domain, ns_t_ptr); if (NETDB_SUCCESS != query_stat) { return query_stat; } // end if size_t msg_count = ns_msg_count(self->msghanlde, ns_s_an); DnsPtrResponse *respobj = (DnsPtrResponse *) malloc(sizeof(DnsPtrResponse) + msg_count * sizeof(char *)); if (NULL == respobj) { return DnsResolver_setError(self, NETDB_INTERNAL); } // end if memset(respobj, 0, sizeof(DnsPtrResponse) + msg_count * sizeof(char *)); respobj->num = 0; for (size_t n = 0; n < msg_count; ++n) { ns_rr rr; int parse_stat = ns_parserr(&self->msghanlde, ns_s_an, n, &rr); if (0 != parse_stat) { goto formerr; } // end if if (ns_t_ptr != ns_rr_type(rr)) { continue; } // end if // NOTE: NS_MAXDNAME で十分なのかイマイチ確証が持てないが, bind8 の dig コマンドの実装でもこの値を使っていたのでいいのではないか. char dnamebuf[NS_MAXDNAME]; int dnamelen = ns_name_uncompress(self->msgbuf, self->msgbuf + self->msglen, ns_rr_rdata(rr), dnamebuf, sizeof(dnamebuf)); if (dnamelen != ns_rr_rdlen(rr)) { goto formerr; } // end if respobj->domain[respobj->num] = strdup(dnamebuf); if (NULL == respobj->domain[respobj->num]) { goto noresource; } // end if ++(respobj->num); } // end for if (0 == respobj->num) { goto formerr; } // end if *resp = respobj; return NETDB_SUCCESS; formerr: DnsPtrResponse_free(respobj); return DnsResolver_setError(self, NO_RECOVERY); noresource: DnsPtrResponse_free(respobj); return DnsResolver_setError(self, NETDB_INTERNAL); } // end function : DnsResolver_lookupPtr
/* Returns 1 with an answer, 0 when reply was old, -1 on fatal errors */ int nb_dns_activity(struct nb_dns_info *nd, struct nb_dns_result *nr, char *errstr) { register int msglen, qtype, atype, n, i; register struct nb_dns_entry *ne, *lastne; socklen_t fromlen; struct sockaddr_storage from; u_long msg[MAXPACKET / sizeof(u_long)]; register char *bp, *ep; register char **ap, **hap; register u_int16_t id; register const u_char *rdata; register u_int32_t rttl = 0; // make compiler happy. register struct hostent *he; register size_t rdlen; ns_msg handle; ns_rr rr; /* This comes from the second half of do_query() */ fromlen = sizeof(from); msglen = recvfrom(nd->s, (char *)msg, sizeof(msg), 0, (struct sockaddr*)&from, &fromlen); if (msglen <= 0) { snprintf(errstr, NB_DNS_ERRSIZE, "recvfrom(): %s", my_strerror(errno)); return (-1); } if (msglen < HFIXEDSZ) { snprintf(errstr, NB_DNS_ERRSIZE, "recvfrom(): undersized: %d", msglen); return (-1); } if (ns_initparse((u_char *)msg, msglen, &handle) < 0) { snprintf(errstr, NB_DNS_ERRSIZE, "ns_initparse(): %s", my_strerror(errno)); nr->host_errno = NO_RECOVERY; return (-1); } /* RES_INSECURE1 style check */ if (_nb_dns_cmpsockaddr((struct sockaddr*)&nd->server, (struct sockaddr*)&from, errstr) < 0) { nr->host_errno = NO_RECOVERY; return (-1); } /* Search for this request */ lastne = NULL; id = ns_msg_id(handle); for (ne = nd->list; ne != NULL; ne = ne->next) { if (ne->id == id) break; lastne = ne; } /* Not an answer to a question we care about anymore */ if (ne == NULL) return (0); /* Unlink this entry */ if (lastne == NULL) nd->list = ne->next; else lastne->next = ne->next; ne->next = NULL; /* RES_INSECURE2 style check */ /* XXX not implemented */ /* Initialize result struct */ memset(nr, 0, sizeof(*nr)); nr->cookie = ne->cookie; qtype = ne->qtype; /* Deal with various errors */ switch (ns_msg_getflag(handle, ns_f_rcode)) { case ns_r_nxdomain: nr->host_errno = HOST_NOT_FOUND; free(ne); return (1); case ns_r_servfail: nr->host_errno = TRY_AGAIN; free(ne); return (1); case ns_r_noerror: break; case ns_r_formerr: case ns_r_notimpl: case ns_r_refused: default: nr->host_errno = NO_RECOVERY; free(ne); return (1); } /* Loop through records in packet */ memset(&rr, 0, sizeof(rr)); memset(&nd->dns_hostent, 0, sizeof(nd->dns_hostent)); he = &nd->dns_hostent.hostent; /* XXX no support for aliases */ he->h_aliases = nd->dns_hostent.host_aliases; he->h_addr_list = nd->dns_hostent.h_addr_ptrs; he->h_addrtype = ne->atype; he->h_length = ne->asize; free(ne); bp = nd->dns_hostent.hostbuf; ep = bp + sizeof(nd->dns_hostent.hostbuf); hap = he->h_addr_list; ap = he->h_aliases; for (i = 0; i < ns_msg_count(handle, ns_s_an); i++) { /* Parse next record */ if (ns_parserr(&handle, ns_s_an, i, &rr) < 0) { if (errno != ENODEV) { nr->host_errno = NO_RECOVERY; return (1); } /* All done */ break; } /* Ignore records that don't answer our query (e.g. CNAMEs) */ atype = ns_rr_type(rr); if (atype != qtype) continue; rdata = ns_rr_rdata(rr); rdlen = ns_rr_rdlen(rr); rttl = ns_rr_ttl(rr); switch (atype) { case T_A: case T_AAAA: if (rdlen != (unsigned int) he->h_length) { snprintf(errstr, NB_DNS_ERRSIZE, "nb_dns_activity(): bad rdlen %d", (int) rdlen); nr->host_errno = NO_RECOVERY; return (-1); } if (bp + rdlen >= ep) { snprintf(errstr, NB_DNS_ERRSIZE, "nb_dns_activity(): overflow 1"); nr->host_errno = NO_RECOVERY; return (-1); } if (nd->dns_hostent.numaddrs + 1 >= MAXADDRS) { snprintf(errstr, NB_DNS_ERRSIZE, "nb_dns_activity(): overflow 2"); nr->host_errno = NO_RECOVERY; return (-1); } memcpy(bp, rdata, rdlen); *hap++ = bp; bp += rdlen; ++nd->dns_hostent.numaddrs; /* Keep looking for more A records */ break; case T_TXT: if (bp + rdlen >= ep) { snprintf(errstr, NB_DNS_ERRSIZE, "nb_dns_activity(): overflow 1 for txt"); nr->host_errno = NO_RECOVERY; return (-1); } memcpy(bp, rdata, rdlen); he->h_name = bp+1; /* First char is a control character. */ nr->hostent = he; nr->ttl = rttl; return (1); case T_PTR: n = dn_expand((const u_char *)msg, (const u_char *)msg + msglen, rdata, bp, ep - bp); if (n < 0) { /* XXX return -1 here ??? */ nr->host_errno = NO_RECOVERY; return (1); } he->h_name = bp; /* XXX check for overflow */ bp += n; /* returned len includes EOS */ /* "Find first satisfactory answer" */ nr->hostent = he; nr->ttl = rttl; return (1); } } nr->hostent = he; nr->ttl = rttl; return (1); }
static void test_res_fake_soa_query(void **state) { int rv; struct __res_state dnsstate; unsigned char answer[ANSIZE]; ns_msg handle; ns_rr rr; /* expanded resource record */ const uint8_t *rrdata; char nameser[MAXDNAME]; char admin[MAXDNAME]; int serial; int refresh; int retry; int expire; int minimum; (void) state; /* unused */ memset(&dnsstate, 0, sizeof(struct __res_state)); rv = res_ninit(&dnsstate); assert_int_equal(rv, 0); rv = res_nquery(&dnsstate, "cwrap.org", ns_c_in, ns_t_soa, answer, sizeof(answer)); assert_in_range(rv, 1, 100); ns_initparse(answer, sizeof(answer), &handle); /* * The query must finish w/o an error, have one answer and the answer * must be a parseable RR of type SOA and have the data as in the fake * hosts file */ assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror); assert_int_equal(ns_msg_count(handle, ns_s_an), 1); assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0); assert_int_equal(ns_rr_type(rr), ns_t_soa); rrdata = ns_rr_rdata(rr); rv = ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), rrdata, nameser, MAXDNAME); assert_int_not_equal(rv, -1); rrdata += rv; rv = ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), rrdata, admin, MAXDNAME); assert_int_not_equal(rv, -1); rrdata += rv; NS_GET32(serial, rrdata); NS_GET32(refresh, rrdata); NS_GET32(retry, rrdata); NS_GET32(expire, rrdata); NS_GET32(minimum, rrdata); assert_string_equal(nameser, "ns1.cwrap.org"); assert_string_equal(admin, "admin.cwrap.org"); assert_int_equal(serial, 2014100457); assert_int_equal(refresh, 3600); assert_int_equal(retry, 300); assert_int_equal(expire, 1814400); assert_int_equal(minimum, 600); }
static void test_res_fake_a_via_cname(void **state) { int rv; struct __res_state dnsstate; unsigned char answer[ANSIZE]; ns_msg handle; ns_rr rr; /* expanded resource record */ const uint8_t *rrdata; char cname[MAXDNAME]; char addr[INET_ADDRSTRLEN]; (void) state; /* unused */ memset(&dnsstate, 0, sizeof(struct __res_state)); rv = res_ninit(&dnsstate); assert_int_equal(rv, 0); /* Query for A record, but the key is a CNAME. The expected result is * that the whole chain of CNAMEs will be included in the answer section * along with the resulting A */ rv = res_nquery(&dnsstate, "rwrap.org", ns_c_in, ns_t_a, answer, sizeof(answer)); assert_in_range(rv, 1, 256); ns_initparse(answer, sizeof(answer), &handle); /* * The query must finish w/o an error, have three answers and the answers * must be a parseable RR of type CNAME and have the cname as in the * fake hosts file */ assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror); assert_int_equal(ns_msg_count(handle, ns_s_an), 3); assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0); assert_int_equal(ns_rr_type(rr), ns_t_cname); rrdata = ns_rr_rdata(rr); rv = ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), rrdata, cname, MAXDNAME); assert_int_not_equal(rv, -1); assert_string_equal(cname, "web.cwrap.org"); assert_int_equal(ns_parserr(&handle, ns_s_an, 1, &rr), 0); assert_int_equal(ns_rr_type(rr), ns_t_cname); rrdata = ns_rr_rdata(rr); rv = ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), rrdata, cname, MAXDNAME); assert_int_not_equal(rv, -1); assert_string_equal(cname, "www.cwrap.org"); assert_int_equal(ns_parserr(&handle, ns_s_an, 2, &rr), 0); assert_int_equal(ns_rr_type(rr), ns_t_a); assert_string_equal(ns_rr_name(rr), "www.cwrap.org"); assert_non_null(inet_ntop(AF_INET, ns_rr_rdata(rr), addr, sizeof(addr))); assert_string_equal(addr, "127.0.0.22"); }
/** * create_naptr_record() */ static NAPTR_record *create_naptr_record(const ns_msg *handle, const ns_rr *rr) { size_t rdchars; const u_char *rdata, *edata; const u_char *message = ns_msg_base(*handle); size_t message_len = ns_msg_size(*handle); char buf[NS_MAXDNAME]; /* defined in nameser.h */ NAPTR_record *naptr_record = malloc(sizeof(NAPTR_record)); memset(naptr_record,0,sizeof(NAPTR_record)); /* ** Domain field */ naptr_record->domain = strdup(ns_rr_name(*rr)); /* ** TTL field */ naptr_record->ttl = ns_rr_ttl(*rr); /* ** Copy from rdata ** (borrowed from BIND-8.2.2 ns_print.c) */ rdata = ns_rr_rdata(*rr); edata = rdata+ns_rr_rdlen(*rr); /* ** Order & preference field */ naptr_record->order = ns_get16(rdata); rdata += NS_INT16SZ; naptr_record->preference = ns_get16(rdata); rdata += NS_INT16SZ; /* ** Flags field */ if((naptr_record->flags = get_rdata_str(rdata,edata,&rdchars))==NULL) { free_naptr_record(naptr_record); return NULL; } rdata += rdchars; /* ** Service field */ if((naptr_record->service = get_rdata_str(rdata,edata,&rdchars))==NULL) { free_naptr_record(naptr_record); return NULL; } rdata += rdchars; /* ** RegExp field */ if((naptr_record->regexp = get_rdata_str(rdata,edata,&rdchars))==NULL) { free_naptr_record(naptr_record); return NULL; } rdata += rdchars; /* ** Replacement field ** Note: dn_expand() sets the first character to '\0' for the root, ** we are going to set it back to '.' */ if(dn_expand(message,message+message_len,rdata,buf,NS_MAXDNAME)==-1) { free_naptr_record(naptr_record); return NULL; } if(buf[0]=='\0') { buf[0]='.'; buf[1]='\0'; } naptr_record->replacement = strdup(buf); return naptr_record; }
static void test_res_fake_cname_query(void **state) { int rv; struct __res_state dnsstate; unsigned char answer[ANSIZE]; ns_msg handle; ns_rr rr; /* expanded resource record */ const uint8_t *rrdata; char cname[MAXDNAME]; char addr[INET_ADDRSTRLEN]; (void) state; /* unused */ memset(&dnsstate, 0, sizeof(struct __res_state)); rv = res_ninit(&dnsstate); assert_int_equal(rv, 0); rv = res_nquery(&dnsstate, "rwrap.org", ns_c_in, ns_t_cname, answer, sizeof(answer)); assert_in_range(rv, 1, 256); ns_initparse(answer, 256, &handle); ns_initparse(answer, sizeof(answer), &handle); /* * The query must finish w/o an error, have one answer and the answer * must be a parseable RR of type CNAME and have the cname as in the * fake hosts file */ assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror); assert_int_equal(ns_msg_count(handle, ns_s_an), 1); assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0); assert_int_equal(ns_rr_type(rr), ns_t_cname); rrdata = ns_rr_rdata(rr); rv = ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), rrdata, cname, MAXDNAME); assert_int_not_equal(rv, -1); assert_string_equal(cname, "web.cwrap.org"); /* The CNAME points to an A record that's present in the additional * section */ assert_int_equal(ns_msg_count(handle, ns_s_ar), 2); assert_int_equal(ns_parserr(&handle, ns_s_ar, 0, &rr), 0); assert_int_equal(ns_rr_type(rr), ns_t_cname); assert_string_equal(ns_rr_name(rr), "web.cwrap.org"); rrdata = ns_rr_rdata(rr); rv = ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), rrdata, cname, MAXDNAME); assert_int_not_equal(rv, -1); assert_string_equal(cname, "www.cwrap.org"); assert_int_equal(ns_parserr(&handle, ns_s_ar, 1, &rr), 0); assert_int_equal(ns_rr_type(rr), ns_t_a); assert_string_equal(ns_rr_name(rr), "www.cwrap.org"); assert_non_null(inet_ntop(AF_INET, ns_rr_rdata(rr), addr, sizeof(addr))); assert_string_equal(addr, "127.0.0.22"); }
// for(int i=0; i<100; i++) { // printf("I won't call perl scripts from 'system' functions!\n"); // } unsigned char* txt_info_for_hostname(const char* domain, int *txt_len, bool decode) { assert(strlen(domain) < 256); FILE *fp; int i=0; char path[100]; std::string real_result; char* result; char* aux_result; char command[325]; // Somewhat arbitrary limit, but txt_len must // be less than 256 characters in size /* Attribution: http://wiki.shellium.org/w/DNS_functions_%28example_program%29 */ unsigned char query_buffer[1024]; ns_msg query_msg; ns_rr query_rr; int query_result = res_query(domain, C_IN, T_TXT, query_buffer, sizeof(query_buffer)); if(query_result == -1) { // TODO: Return an error code or something goto error_ret; } if(ns_initparse(query_buffer, query_result, &query_msg) == -1) { goto error_ret; } for (i = 0; i < ns_msg_count(query_msg, ns_s_an); i++) { if (ns_parserr(&query_msg, ns_s_an, i, &query_rr)) { goto error_ret; } if (ns_rr_type(query_rr) == ns_t_txt) { const unsigned char* data1 = ns_rr_rdata(query_rr); aux_result = (char*) malloc(sizeof(char) * ns_rr_rdlen(query_rr)); memcpy(aux_result, data1, ns_rr_rdlen(query_rr)); if(!aux_result) { goto error_ret; } printf("NS_TXT!\n"); //printf("%s", (const char*)data1); //printf("\n"); print_buffer((const char*)data1, ns_rr_rdlen(query_rr) + 32); //printf("ENDOFTEXT\n"); } } if(decode) { sprintf(command, "nslookup %s | ./extract_and_decode.pl", domain); } else { sprintf(command, "nslookup %s | ./extract.pl", domain); } /* Open the command for reading. */ fp = popen(command, "r"); if (fp == NULL) { return NULL; } /* Read the output a line at a time - output it. */ while (fgets(path, sizeof(path)-1, fp) != NULL) { real_result += path; } /* close */ pclose(fp); result = (char *)malloc(sizeof(char) * (real_result.length() + 1)); if(!result) { return NULL; } strcpy(result, real_result.c_str()); *txt_len = real_result.length(); print_buffer(result, *txt_len); print_buffer(aux_result, query_result); return (unsigned char*)result; error_ret: *txt_len = 0; return NULL; }