static void printer_hes_callback(void *arg, int status, unsigned char *abuf, int alen) { struct printer_poll_args *pargs = (struct printer_poll_args *) arg; struct serverstate *state = pargs->state; struct printer *printer = pargs->printer; char **vec = NULL, *p, *q, *errmem; if (status == ARES_EDESTRUCTION) { syslog(LOG_DEBUG, "printer_hes_callback: printer %s hesiod query " "halted for channel destruction", printer->name); free(pargs); return; } if (status != ARES_SUCCESS) { syslog(LOG_ERR, "printer_hes_callback: could not resolve Hesiod pcap " "for printer %s: %s", printer->name, ares_strerror(status, &errmem)); ares_free_errmem(errmem); goto failure; } /* Parse the result buffer into text records. */ vec = hesiod_parse_result(state->hescontext, abuf, alen); if (!vec || !*vec) { syslog(LOG_ERR, "printer_hes_callback: could not parse Hesiod pcap " "result for printer %s: %m", printer->name); goto failure; } /* Look for the print server name. */ p = strchr(*vec, ':'); while (p) { if (strncmp(p + 1, "rm=", 3) == 0) break; p = strchr(p + 1, ':'); } if (!p) { syslog(LOG_ERR, "printer_hes_callback: can't find print server name in " "Hesiod pcap result for printer %s", printer->name); goto failure; } p += 4; q = p; while (*q && *q != ':') q++; *q = 0; syslog(LOG_DEBUG, "printer_hes_callback: printer %s starting query for %s", printer->name, p); ares_gethostbyname(state->channel, p, AF_INET, printer_host_callback, pargs); hesiod_free_list(state->hescontext, vec); return; failure: if (vec) hesiod_free_list(state->hescontext, vec); printer->timer = timer_set_rel(60, printer_poll, pargs); }
static void callback(void *arg, int status, unsigned char *abuf, int alen) { char *name = (char *) arg, *errmem; int id, qr, opcode, aa, tc, rd, ra, rcode, i; unsigned int qdcount, ancount, nscount, arcount; const unsigned char *aptr; /* Display the query name if given. */ if (name) printf("Answer for query %s:\n", name); /* Display an error message if there was an error, but only stop if * we actually didn't get an answer buffer. */ if (status != ARES_SUCCESS) { printf("%s\n", ares_strerror(status, &errmem)); ares_free_errmem(errmem); if (!abuf) return; } /* Won't happen, but check anyway, for safety. */ if (alen < HFIXEDSZ) return; /* Parse the answer header. */ id = DNS_HEADER_QID(abuf); qr = DNS_HEADER_QR(abuf); opcode = DNS_HEADER_OPCODE(abuf); aa = DNS_HEADER_AA(abuf); tc = DNS_HEADER_TC(abuf); rd = DNS_HEADER_RD(abuf); ra = DNS_HEADER_RA(abuf); rcode = DNS_HEADER_RCODE(abuf); qdcount = DNS_HEADER_QDCOUNT(abuf); ancount = DNS_HEADER_ANCOUNT(abuf); nscount = DNS_HEADER_NSCOUNT(abuf); arcount = DNS_HEADER_ARCOUNT(abuf); /* Display the answer header. */ printf("id: %d\n", id); printf("flags: %s%s%s%s%s\n", qr ? "qr " : "", aa ? "aa " : "", tc ? "tc " : "", rd ? "rd " : "", ra ? "ra " : ""); printf("opcode: %s\n", opcodes[opcode]); printf("rcode: %s\n", rcodes[rcode]); /* Display the questions. */ printf("Questions:\n"); aptr = abuf + HFIXEDSZ; for (i = 0; i < qdcount; i++) { aptr = display_question(aptr, abuf, alen); if (aptr == NULL) return; } /* Display the answers. */ printf("Answers:\n"); for (i = 0; i < ancount; i++) { aptr = display_rr(aptr, abuf, alen); if (aptr == NULL) return; } /* Display the NS records. */ printf("NS records:\n"); for (i = 0; i < nscount; i++) { aptr = display_rr(aptr, abuf, alen); if (aptr == NULL) return; } /* Display the additional records. */ printf("Additional records:\n"); for (i = 0; i < arcount; i++) { aptr = display_rr(aptr, abuf, alen); if (aptr == NULL) return; } }
static void printer_host_callback(void *arg, int status, struct hostent *host) { struct printer_poll_args *pargs = (struct printer_poll_args *) arg; struct printer *printer = pargs->printer; int s = -1, lport = IPPORT_RESERVED - 1, flags; unsigned short port; struct servent *servent; struct sockaddr_in sin; char *errmem; if (status == ARES_EDESTRUCTION) { syslog(LOG_DEBUG, "printer_host_callback: printer %s hostname query " "halted for channel destruction", printer->name); free(pargs); return; } if (status != ARES_SUCCESS) { syslog(LOG_ERR, "printer_host_callback: printer %s can't resolve print " "server name: %s", printer->name, ares_strerror(status, &errmem)); ares_free_errmem(errmem); goto failure; } s = rresvport(&lport); if (s < 0) { syslog(LOG_ERR, "printer_host_callback: printer %s can't get reserved " "port", printer->name); goto failure; } /* Set s non-blocking so we can do a non-blocking connect. */ flags = fcntl(s, F_GETFL); fcntl(s, F_SETFL, flags | O_NONBLOCK); servent = getservbyname("printer", "tcp"); port = (servent) ? servent->s_port : htons(PRINTER_FALLBACK_PORT); memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; memcpy(&sin.sin_addr, host->h_addr, sizeof(sin.sin_addr)); sin.sin_port = port; if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == -1 && errno != EINPROGRESS) { syslog(LOG_ERR, "printer_host_callback: printer %s can't connect to " "print server %s: %m", printer->name, host->h_name); goto failure; } /* Set up the request we want to send; the main loop will call * printer_handle_output() when the socket selects true for * writing. */ printer->s = s; printer->to_send = 1; sprintf(printer->buf, "\3%.*s\n", (int)(sizeof(printer->buf) - 3), printer->name); printer->buflen = strlen(printer->buf); printer->jobs_counted = 0; printer->up_so_far = 1; syslog(LOG_DEBUG, "printer_host_callback: printer %s queued %d-byte query", printer->name, printer->buflen); free(pargs); return; failure: if (s >= 0) close(s); printer->timer = timer_set_rel(60, printer_poll, pargs); return; }
int main(int argc, char **argv) { ares_channel channel; int c, i, optmask = ARES_OPT_FLAGS, dnsclass = C_IN, type = T_A; int status, nfds, count; struct ares_options options; struct hostent *hostent; fd_set read_fds, write_fds; struct timeval *tvp, tv; char *errmem; options.flags = ARES_FLAG_NOCHECKRESP; options.servers = NULL; options.nservers = 0; while ((c = getopt(argc, argv, "f:s:c:t:T:U:")) != -1) { switch (c) { case 'f': /* Add a flag. */ for (i = 0; i < nflags; i++) { if (strcmp(flags[i].name, optarg) == 0) break; } if (i == nflags) usage(); options.flags |= flags[i].value; break; case 's': /* Add a server, and specify servers in the option mask. */ hostent = gethostbyname(optarg); if (!hostent || hostent->h_addrtype != AF_INET) { fprintf(stderr, "adig: server %s not found.\n", optarg); return 1; } options.servers = realloc(options.servers, (options.nservers + 1) * sizeof(struct in_addr)); if (!options.servers) { fprintf(stderr, "Out of memory!\n"); return 1; } memcpy(&options.servers[options.nservers], hostent->h_addr, sizeof(struct in_addr)); options.nservers++; optmask |= ARES_OPT_SERVERS; break; case 'c': /* Set the query class. */ for (i = 0; i < nclasses; i++) { if (strcasecmp(classes[i].name, optarg) == 0) break; } if (i == nclasses) usage(); dnsclass = classes[i].value; break; case 't': /* Set the query type. */ for (i = 0; i < ntypes; i++) { if (strcasecmp(types[i].name, optarg) == 0) break; } if (i == ntypes) usage(); type = types[i].value; break; case 'T': /* Set the TCP port number. */ if (!isdigit((unsigned char)*optarg)) usage(); options.tcp_port = strtol(optarg, NULL, 0); optmask |= ARES_OPT_TCP_PORT; break; case 'U': /* Set the UDP port number. */ if (!isdigit((unsigned char)*optarg)) usage(); options.udp_port = strtol(optarg, NULL, 0); optmask |= ARES_OPT_UDP_PORT; break; } } argc -= optind; argv += optind; if (argc == 0) usage(); status = ares_init_options(&channel, &options, optmask); if (status != ARES_SUCCESS) { fprintf(stderr, "ares_init_options: %s\n", ares_strerror(status, &errmem)); ares_free_errmem(errmem); return 1; } /* Initiate the queries, one per command-line argument. If there is * only one query to do, supply NULL as the callback argument; * otherwise, supply the query name as an argument so we can * distinguish responses for the user when printing them out. */ if (argc == 1) ares_query(channel, *argv, dnsclass, type, callback, (char *) NULL); else { for (; *argv; argv++) ares_query(channel, *argv, dnsclass, type, callback, *argv); } /* Wait for all queries to complete. */ while (1) { FD_ZERO(&read_fds); FD_ZERO(&write_fds); nfds = ares_fds(channel, &read_fds, &write_fds); if (nfds == 0) break; tvp = ares_timeout(channel, NULL, &tv); count = select(nfds, &read_fds, &write_fds, NULL, tvp); if (count < 0 && errno != EINVAL) { perror("select"); return 1; } ares_process(channel, &read_fds, &write_fds); } ares_destroy(channel); return 0; }