/* * ldns-notify.c - ldns-notify(8) * * Copyright (c) 2001-2008, NLnet Labs, All right reserved * * See LICENSE for the license * * send a notify packet to a server */ #include "config.h" /* ldns */ #include #ifdef HAVE_NETDB_H #include #endif #include static int verbose = 1; static int max_num_retry = 15; /* times to try */ static void usage(void) { fprintf(stderr, "usage: ldns-notify [other options] -z zone \n"); fprintf(stderr, "Ldns notify utility\n\n"); fprintf(stderr, " Supported options:\n"); fprintf(stderr, "\t-z zone\t\tThe zone\n"); fprintf(stderr, "\t-s version\tSOA version number to include\n"); fprintf(stderr, "\t-y key:data\tTSIG sign the query\n"); fprintf(stderr, "\t-p port\t\tport to use to send to\n"); fprintf(stderr, "\t-v\t\tPrint version information\n"); fprintf(stderr, "\t-d\t\tPrint verbose debug information\n"); fprintf(stderr, "\t-r num\t\tmax number of retries (%d)\n", max_num_retry); fprintf(stderr, "\t-h\t\tPrint this help information\n\n"); fprintf(stderr, "Report bugs to \n"); exit(1); } static void version(void) { fprintf(stderr, "%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION); fprintf(stderr, "Written by NLnet Labs.\n\n"); fprintf(stderr, "Copyright (C) 2001-2008 NLnet Labs. This is free software.\n" "There is NO warranty; not even for MERCHANTABILITY or FITNESS\n" "FOR A PARTICULAR PURPOSE.\n"); exit(0); } static void notify_host(int s, struct addrinfo* res, uint8_t* wire, size_t wiresize, const char* addrstr) { int timeout_retry = 5; /* seconds */ int num_retry = max_num_retry; fd_set rfds; struct timeval tv; int retval = 0; ssize_t received = 0; int got_ack = 0; socklen_t addrlen = 0; uint8_t replybuf[2048]; ldns_status status; ldns_pkt* pkt = NULL; while(!got_ack) { /* send it */ if(sendto(s, (void*)wire, wiresize, 0, res->ai_addr, res->ai_addrlen) == -1) { printf("warning: send to %s failed: %s\n", addrstr, strerror(errno)); #ifndef USE_WINSOCK close(s); #else closesocket(s); #endif return; } /* wait for ACK packet */ FD_ZERO(&rfds); FD_SET(s, &rfds); #ifndef S_SPLINT_S tv.tv_sec = timeout_retry; /* seconds */ #endif tv.tv_usec = 0; /* microseconds */ retval = select(s + 1, &rfds, NULL, NULL, &tv); if (retval == -1) { printf("error waiting for reply from %s: %s\n", addrstr, strerror(errno)); #ifndef USE_WINSOCK close(s); #else closesocket(s); #endif return; } if(retval == 0) { num_retry--; if(num_retry == 0) { printf("error: failed to send notify to %s.\n", addrstr); exit(1); } printf("timeout (%d s) expired, retry notify to %s.\n", timeout_retry, addrstr); } if (retval == 1) { got_ack = 1; } } /* got reply */ addrlen = res->ai_addrlen; received = recvfrom(s, (void*)replybuf, sizeof(replybuf), 0, res->ai_addr, &addrlen); res->ai_addrlen = addrlen; #ifndef USE_WINSOCK close(s); #else closesocket(s); #endif if (received == -1) { printf("recv %s failed: %s\n", addrstr, strerror(errno)); return; } /* check reply */ status = ldns_wire2pkt(&pkt, replybuf, (size_t)received); if(status != LDNS_STATUS_OK) { ssize_t i; printf("Could not parse reply packet: %s\n", ldns_get_errorstr_by_id(status)); printf("hexdump of reply: "); for(i=0; iai_next) { int s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if(s == -1) continue; /* send the notify */ notify_host(s, res, wire, wiresize, argv[i]); } freeaddrinfo(res0); } ldns_pkt_free(notify); free(wire); return 0; }