• Patch: Elm ME+ 2.5 PLalpha46 -> Elm ME+ 2.5 PLalpha47 [6/7] (5/5)

    From Kari Hurtta@21:1/5 to All on Sat Feb 10 14:47:10 2018
    [continued from previous message]

    + walk_ptr += sizeof (X.ip4addr);
    + size_left -= sizeof (X.ip4addr);
    +
    + addr = inet_ntop(AF_INET,& (X.ip4addr),
    + address,sizeof address);
    +
    + if (addr) {
    + printf(" = %s",addr);
    + }
    + }
    +
    + break;
    + case ns_t_ns:
    + printf(" name server");
    +
    + if (size_left > 0) {
    + char domain_name[1024];
    + int compressed_len;
    +
    + errno = 0;
    + compressed_len =
    + ns_name_uncompress(ns_msg_base((*parsed)),
    + ns_msg_end((*parsed)),
    + walk_ptr,
    + domain_name,
    + sizeof domain_name);
    +
    + if (compressed_len < 0) {
    + printf(", failed to expand name");
    + break;
    + }
    +
    + walk_ptr += compressed_len;
    + size_left -= compressed_len;
    +
    + printf(" = %s",domain_name);
    + }
    +
    +
    + break;
    + case ns_t_cname:
    + printf(" canonical name");
    +
    + if (size_left > 0) {
    + char domain_name[1024];
    + int compressed_len;
    +
    + errno = 0;
    + compressed_len =
    + ns_name_uncompress(ns_msg_base((*parsed)),
    + ns_msg_end((*parsed)),
    + walk_ptr,
    + domain_name,
    + sizeof domain_name);
    +
    + if (compressed_len < 0) {
    + printf(", failed to expand name");
    + break;
    + }
    +
    + walk_ptr += compressed_len;
    + size_left -= compressed_len;
    +
    + printf(" = %s",domain_name);
    + }
    +
    + break;
    + case ns_t_mx:
    + printf(" mail handler");
    +
    + if (size_left > 2) {
    + int precedence;
    + char domain_name[1024];
    + int compressed_len;
    +
    + precedence = ns_get16(walk_ptr);
    + walk_ptr += 2;
    + size_left -= 2;
    +
    + compressed_len =
    + ns_name_uncompress(ns_msg_base((*parsed)),
    + ns_msg_end((*parsed)),
    + walk_ptr,
    + domain_name,
    + sizeof domain_name);
    +
    + if (compressed_len < 0) {
    + printf(", failed to expand name");
    + break;
    + }
    +
    + walk_ptr += compressed_len;
    + size_left -= compressed_len;
    +
    + printf(" = %s precedence=%d",domain_name,precedence);
    + }
    +
    + break;
    + case ns_t_aaaa:
    + printf(" IPv6 address");
    +
    + if (size_left >= sizeof (X.ip6addr)) {
    + char address[256];
    + const char *addr;
    +
    + memcpy(X.buffer,walk_ptr,sizeof (X.ip6addr));
    +
    + walk_ptr += sizeof (X.ip6addr);
    + size_left -= sizeof (X.ip6addr);
    +
    + addr = inet_ntop(AF_INET6,& (X.ip6addr),
    + address,sizeof address);
    +
    + if (addr) {
    + printf(" = %s",addr);
    + }
    + }
    +
    + break;
    +
    + case ns_t_txt:
    + printf(" text record");
    +
    + n = 0;
    + while (size_left > 0) {
    + char text[256];
    +
    + int len = *walk_ptr;
    +
    + if (len > size_left + 1) {
    + printf(", failed to read text record");
    + break;
    + }
    +
    + walk_ptr ++;
    + size_left --;
    +
    + memcpy(text,walk_ptr,len);
    + text[len] = '\0';
    +
    + walk_ptr += len;
    + size_left -= len;
    +
    + if (n++ > 0) {
    + printf(",\n text record");
    + }
    +
    + printf(" = %s",text);
    + }
    +
    + break;
    +
    + case ns_t_srv:
    + printf(" server");
    +
    + if (size_left > 6) {
    + int priority, weight, port;
    + char domain_name[1024];
    + int compressed_len;
    +
    + priority = ns_get16(walk_ptr);
    + walk_ptr += 2;
    + size_left -= 2;
    +
    + weight = ns_get16(walk_ptr);
    + walk_ptr += 2;
    + size_left -= 2;
    +
    + port = ns_get16(walk_ptr);
    + walk_ptr += 2;
    + size_left -= 2;
    +
    + compressed_len =
    + ns_name_uncompress(ns_msg_base((*parsed)),
    + ns_msg_end((*parsed)),
    + walk_ptr,
    + domain_name,
    + sizeof domain_name);
    +
    + if (compressed_len < 0) {
    + printf(", failed to expand name");
    + break;
    + }
    +
    + walk_ptr += compressed_len;
    + size_left -= compressed_len;
    +
    + printf(" = %s priority=%d weight=%d port=%d",
    + domain_name,priority,weight,port);
    + }
    + break;
    +
    + case ns_t_ptr:
    + printf(" domain name");
    +
    + if (size_left > 0) {
    + char domain_name[1024];
    + int compressed_len;
    +
    + errno = 0;
    + compressed_len =
    + ns_name_uncompress(ns_msg_base((*parsed)),
    + ns_msg_end((*parsed)),
    + walk_ptr,
    + domain_name,
    + sizeof domain_name);
    +
    + if (compressed_len < 0) {
    + printf(", failed to expand name");
    + break;
    + }
    +
    + walk_ptr += compressed_len;
    + size_left -= compressed_len;
    +
    + printf(" = %s",domain_name);
    + }
    +
    +
    + break;
    + }
    +
    + if (0 != size_left) {
    + printf(", %d trailing bytes",size_left);
    + }
    +
    + printf("\n");
    + }
    +
    + }
    + }
    +
    + #if defined(__STDC__)
    + int same_question_rr(ns_rr *rr1, ns_rr *rr2);
    + #endif
    +
    + int same_question_rr(rr1,rr2)
    + ns_rr *rr1;
    + ns_rr *rr2;
    + {
    + char *name1 = ns_rr_name((*rr1));
    + char *name2 = ns_rr_name((*rr2));
    + ns_class recclass1 = ns_rr_class((*rr1));
    + ns_class recclass2 = ns_rr_class((*rr2));
    + ns_type rectype1 = ns_rr_type((*rr1));
    + ns_type rectype2 = ns_rr_type((*rr2));
    +
    + if (! name1 || ! name2) {
    + fprintf(stderr,"same_question_rr: no name\n");
    + return 0;
    + }
    +
    + if (0 != strcmp(name1,name2)) {
    + fprintf(stderr,"same_question_rr: name mismatch: %s <> %s\n",
    + name1,name2);
    + return 0;
    + }
    +
    + if (recclass1 != recclass2) {
    + fprintf(stderr,"same_question_rr: %s: class mismatch: %d <> %d\n",
    + name1,recclass1,recclass2);
    + return 0;
    + }
    +
    + if (rectype1 != rectype2) {
    + fprintf(stderr,"same_question_rr: %s: rectype mismatch: %d <> %d\n",
    + name1,rectype1,rectype2);
    + return 0;
    + }
    +
    + return 1;
    + }
    +
    + #if defined(__STDC__)
    + int query_it (const char *name, ns_type q_type, char *domain);
    + #endif
    + int query_it(name,q_type,domain)
    + const char *name;
    + ns_type q_type;
    + char *domain;
    + {
    + const char * name1 = name;
    + int r = 0;
    + int res;
    +
    + unsigned char query[1024];
    + int qlen;
    + ns_msg parsed_query;
    + int count,count1,count2;
    +
    + u_int16_t id1,id2;
    + int recnum;
    +
    + unsigned char answer[1024];
    + int anslen;
    + ns_msg parsed_answer;
    + int trailing_dot = 0;
    +
    + int a = strlen(name);
    + ns_rcode rcode;
    + char * name_buffer = NULL;
    +
    + errno = 0;
    +
    + if (a > 0 && '.' == name[a-1]) {
    + trailing_dot = 1;
    +
    + if (domain) {
    + fprintf(stderr, "%s: internal error - trailing dot and domain %s set\n",
    + name,domain);
    +
    + r = -1;
    + goto fail;
    + }
    +
    + } else if (domain && domain[0]) {
    + int d = strlen(domain);
    +
    + name_buffer = malloc(a+d+2);
    +
    + if (!name_buffer) {
    + int err = errno;
    + fprintf(stderr, "malloc %s.%s failed",
    + name,domain);
    + if (0 != err) {
    + fprintf(stderr," errno=%d %s",err,strerror(err));
    + }
    +
    + r = -1;
    + goto fail;
    + }
    +
    + memcpy(name_buffer,name,a);
    + name_buffer[a] = '.';
    + memcpy(name_buffer+a+1,domain,d);
    + name_buffer[a+d+1] = '\0';
    +
    + name1 = name_buffer;
    + }
    +
    + errno = 0;
    +
    + qlen = res_mkquery(QUERY,name1,ns_c_in,q_type,
    + NULL,0 /* Only used with IQUERY */,
    + NULL /* Only used with dynamic update */,
    + query, sizeof query);
    +
    + if (qlen < 0) {
    + int err = errno;
    + fprintf(stderr, "res_mkquery %s: h_errno=%d ",
    + name1,h_errno);
    + if (0 != err) {
    + fprintf(stderr," errno=%d %s",err,strerror(err));
    + }
    +
    + fprintf(stderr, "\n");
    + r = -1;
    + goto fail;
    + }
    +
    + printf("res_mkquery %s: query %d bytes\n",
    + name1,qlen);
    +
    + errno = 0;
    + res = ns_initparse(query,qlen,&parsed_query);
    + if (res < 0) {
    + int err = errno;
    +
    + fprintf (stderr,"%s: failed to parse query (ns_initparse)",
    + name1);
    +
    + if (0 != err) {
    + fprintf(stderr," errno=%d %s",err,strerror(err));
    + }
    +
    + fprintf(stderr, "\n");
    + r = -1;
    + goto fail;
    + }
    +
    + print_parsed(name1,&parsed_query,"query");
    +
    + anslen = res_send(query,qlen,answer,sizeof answer);
    +
    + if (anslen < 0) {
    + int err = errno;
    + fprintf(stderr, "%s: h_errno=%d",name1,h_errno);
    +
    + switch(h_errno) {
    + case HOST_NOT_FOUND:
    + fprintf(stderr, " name not found");
    + break;
    + case NO_DATA:
    + fprintf(stderr, " no %s record",name1);
    + break;
    + case TRY_AGAIN:
    + fprintf(stderr, " not found yet");
    + break;
    + }
    +
    + if (0 != err) {
    + fprintf(stderr," errno=%d %s",err,strerror(err));
    + }
    +
    + if (err == ECONNREFUSED)
    + r = -1;
    + else if (err == ETIMEDOUT)
    + r = -3;
    + else if (TRY_AGAIN == h_errno)
    + r = -3;
    +
    + fprintf(stderr, "\n");
    + goto fail;
    + }
    +
    + printf("res_send %s: answer %d bytes\n",
    + name1,anslen);
    +
    + errno = 0;
    + res = ns_initparse(answer,anslen,&parsed_answer);
    + if (res < 0) {
    + int err = errno;
    +
    + fprintf (stderr,"%s: failed to parse answer (ns_initparse)",
    + name1);
    +
    + if (0 != err) {
    + fprintf(stderr," errno=%d %s",err,strerror(err));
    + }
    +
    + fprintf(stderr, "\n");
    + r = -1;
    + goto fail;
    + }
    +
    + print_parsed(name1,&parsed_answer,"answer");
    +
    + id1 = ns_msg_id(parsed_query);
    + id2 = ns_msg_id(parsed_answer);
    +
    + if (id1 != id2) {
    + fprintf(stderr, "%s id mismatch: query %d <> answer %d\n",
    + name1,id1,id2);
    + r = -1;
    + goto fail;
    + }
    +
    + count = ns_msg_count(parsed_query, ns_s_qd);
    + count1 = ns_msg_count(parsed_answer, ns_s_qd);
    +
    + if (count != 1 || count1 != 1) {
    + fprintf(stderr, "%s -- on query %d records -- on aswer %d records on question section\n",
    + name1,count,count1);
    + r = -1;
    + goto fail;
    +
    + } else {
    + ns_rr rr1;
    + ns_rr rr2;
    +
    + res = ns_parserr(&parsed_query,ns_s_qd,0,&rr1);
    + if (res < 0) {
    + fprintf (stderr,"%s: failed to parse question (ns_parserr)\n",name1); + r = -1;
    + goto fail;
    + }
    +
    + res = ns_parserr(&parsed_answer,ns_s_qd,0,&rr2);
    + if (res < 0) {
    + fprintf (stderr,"%s: failed to parse answer (ns_parserr)\n",name1);
    + r = -1;
    + goto fail;
    + }
    +
    + if (! same_question_rr(&rr1,&rr2)) {
    + fprintf (stderr,"%s: answer does not match to question\n",name1);
    + r = -1;
    + goto fail;
    + }
    +
    + }
    +
    + rcode = ns_msg_getflag(parsed_answer, ns_f_rcode);
    + switch (rcode) {
    + case ns_r_noerror:
    + r = 2;
    + break;
    + case ns_r_formerr: fprintf(stderr,"%s: format error\n",name1);
    + r = -1;
    + goto fail;
    + case ns_r_servfail: fprintf(stderr,"%s: server failure\n",name1);
    + r = -1;
    + goto fail;
    + case ns_r_nxdomain: fprintf(stderr,"%s: name not found\n", name1);
    + r = 0;
    + goto fail;
    + case ns_r_notimpl: fprintf(stderr,"%s: not implemented\n",name1);
    + r = -1;
    + goto fail;
    + case ns_r_refused: fprintf(stderr,"%s: operation refused\n",name1);
    + r = 0;
    + goto fail;
    + default:
    + fprintf(stderr,"%s: unexpected rcode %d\n",name1,rcode);
    + r = -1;
    + goto fail;
    + }
    +
    + count2 = ns_msg_count(parsed_answer, ns_s_an);
    + for (recnum = 0; recnum < count2 && r != 1; recnum++) {
    + ns_rr rr;
    +
    + r = ns_parserr(&parsed_answer,ns_s_an,recnum,&rr);
    + if (r < 0) {
    + fprintf (stderr,"%s: failed to parse answer (ns_parserr), %d\n",name1, recnum);
    + r = -1;
    + goto fail;
    + }
    +
    + if (ns_rr_class(rr) == ns_c_in &&
    + (ns_rr_type(rr) == q_type ||
    + ns_rr_type(rr) == ns_t_cname) &&
    + ns_rr_name(rr)) {
    +
    + if (0 == strcmp(name1, ns_rr_name(rr))) {
    +
    + printf ("%s: got answer for %s\n",name,name1);
    + r = 1;
    + } else if (trailing_dot && 0 == strncmp(name,ns_rr_name(rr),a-1)) {
    + printf ("%s: %s matches without trailing dot\n",name,ns_rr_name(rr)); + r = 1;
    + } else if (!name1[0] && 0 == strcmp(ns_rr_name(rr),".")) {
    + printf ("empty name matches to %s\n",ns_rr_name(rr));
    + r = 1;
    + }
    + }
    + }
    +
    + fail:
    + if (name_buffer)
    + free(name_buffer);
    + return r;
    + }
    +
    + #if defined(__STDC__)
    + int main (int argc, char * argv[]);
    + #endif
    +
    + int main (argc,argv)
    + int argc;
    + char * argv[];
    + {
    + int r = 0;
    +
    + unsigned char answer[1024];
    + int anslen;
    +
    + unsigned char query[1024];
    + int qlen;
    +
    + ns_msg parsed_query;
    + ns_type q_type;
    +
    + char * name;
    +
    +
    + if (argc != 4) {
    + USAGE:
    + fprintf(stderr, "Usage: %s [query|search] [a|ns|mx|aaaa|txt|srv|ptr] <name>\n",argv[0]);
    + exit(1);
    + }
    +
    + if (0 == strcasecmp(argv[2],"a"))
    + q_type = ns_t_a;
    + else if (0 == strcasecmp(argv[2],"ns"))
    + q_type = ns_t_ns;
    + else if (0 == strcasecmp(argv[2],"cname"))
    + q_type = ns_t_cname;
    + else if (0 == strcasecmp(argv[2],"mx"))
    + q_type = ns_t_mx;
    + else if (0 == strcasecmp(argv[2],"aaaa"))
    + q_type = ns_t_aaaa;
    + else if (0 == strcasecmp(argv[2],"txt"))
    + q_type = ns_t_txt;
    + else if (0 == strcasecmp(argv[2],"srv"))
    + q_type = ns_t_srv;
    + else if (0 == strcasecmp(argv[2],"ptr"))
    + q_type = ns_t_ptr;
    + else
    + goto USAGE;
    +
    + name = argv[3];
    +
    + if (0 == strcmp(argv[1],"query")) {
    + r = query_it(name,q_type,NULL);
    +
    + if (r < 0) {
    +
    + if (-3 == r)
    + exit(3);
    +
    + exit(2);
    + }
    +
    + } else if (0 == strcmp(argv[1],"search")) {
    +
    + /* This should be similar than res_search */
    +
    + int dots = 0;
    + char *c;
    + char * found_dot = NULL;
    + const char * alias;
    +
    + res_init();
    +
    + for (c = name;*c; c++) {
    + if ('.' == *c) {
    + dots++;
    + found_dot = c;
    + }
    + }
    +
    + if (found_dot && !found_dot[1]) {
    + printf("%s: trailing dot\n",name);
    + r = query_it(name,q_type,NULL);
    +
    + if (r < 0) {
    +
    + if (-3 == r)
    + exit(3);
    +
    + exit(2);
    + }
    +
    + } else if (!dots && (alias = hostalias(name))) {
    + printf("%s: No dots, searching alias: %s\n",
    + name,alias);
    +
    + r = query_it(alias,q_type,NULL);
    +
    + if (r < 0) {
    + exit(2);
    + }
    +
    + } else {
    + char * default_domain_searched = NULL;
    + int root_searched = 0;
    +
    + if (!dots && 0 != (_res.options & RES_DEFNAMES)) {
    + printf("%s: No dots, (RES_DEFNAMES) searching from default domain: %s\n",
    + name,_res.defdname);
    +
    + default_domain_searched = _res.defdname;
    +
    + if ( ! _res.defdname[0] || 0 == strcmp(_res.defdname,".")) {
    + printf(" ... default domain is root\n");
    + root_searched = 1;
    + }
    +
    + r = query_it(name,q_type,_res.defdname);
    +
    + } else if (dots >= _res.ndots) {
    + printf("%s: %d dots, doing absolute query (ndots:%d)\n",
    + name,dots,_res.ndots);
    +
    + r = query_it(name,q_type,NULL);
    + root_searched = 1;
    +
    + if (r < 0) {
    + exit(2);
    + }
    + }
    +
    + if (!r && 0 != (_res.options & RES_DNSRCH) &&
    + (dots ||
    + 0 != (_res.options & RES_DEFNAMES))
    + ) {
    + int x;
    +
    + printf("%s: %d dots%s, (RES_DNSRCH) using search list\n",
    + name,dots,
    + 0 != (_res.options & RES_DEFNAMES) ? " (RES_DEFNAMES)" : "");
    +
    + for (x = 0 ;
    + x < (sizeof _res.dnsrch) / sizeof (_res.dnsrch[0]) &&
    + _res.dnsrch[x] && !r; x++) {
    +
    + if (default_domain_searched &&
    + 0 == strcmp(default_domain_searched,
    + _res.dnsrch[x])) {
    +
    + printf ("skipping %d: %s (default domain already searched)\n",
    + x, _res.dnsrch[x]);
    +
    + } else {
    + int is_root =
    + ( ! _res.dnsrch[x][0] || 0 == strcmp( _res.dnsrch[x],"."));
    +
    + if (root_searched && is_root) {
    + printf ("skipping %d: %s (root already searched)\n",
    + x, _res.dnsrch[x]);
    + } else {
    +
    + printf ("searching %d: %s%s\n",x, _res.dnsrch[x],
    + is_root ? " (is root)" : "");
    +
    + r = query_it(name,q_type,_res.dnsrch[x]);
    +
    + if (is_root)
    + root_searched = 1;
    +
    + if (r < 0) {
    +
    + if (-3 == r)
    + exit(3);
    +
    + exit(2);
    + }
    + }
    + }
    + }
    + }
    +
    +
    + if (!r && !root_searched
    +
    + #ifdef RES_NOTLDQUERY
    + && (dots || 0 == (_res.options & RES_NOTLDQUERY))
    + #endif
    + ) {
    +
    + printf("%s: doing absolute query\n",
    + name);
    +
    + r = query_it(name,q_type,NULL);
    + root_searched = 1;
    +
    + if (r < 0) {
    + exit(2);
    + }
    + }
    + }
    +
    + } else
    + goto USAGE;
    +
    + if (!r) {
    + fprintf(stderr,"%s not found\n",name);
    + exit(2);
    + } else if (2 == r) {
    + fprintf(stderr,"%s: no %s record\n",
    + name,argv[2]);
    + exit(2);
    + }
    +
    + exit(0);
    + }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)