/** parse args into delegpt */ static struct delegpt* parse_delegpt(SSL* ssl, struct regional* region, char* args, uint8_t* root) { /* parse args and add in */ char* p = args; char* todo; struct delegpt* dp = delegpt_create(region); struct sockaddr_storage addr; socklen_t addrlen; if(!dp || !delegpt_set_name(dp, region, root)) { (void)ssl_printf(ssl, "error out of memory\n"); return NULL; } while(p) { todo = p; p = strchr(p, ' '); /* find next spot, if any */ if(p) { *p++ = 0; /* end this spot */ p = skipwhite(p); /* position at next spot */ } /* parse address */ if(!extstrtoaddr(todo, &addr, &addrlen)) { (void)ssl_printf(ssl, "error cannot parse" " IP address '%s'\n", todo); return NULL; } /* add address */ if(!delegpt_add_addr(dp, region, &addr, addrlen, 0, 0, 1)) { (void)ssl_printf(ssl, "error out of memory\n"); return NULL; } } return dp; }
/** open TCP socket to svr */ static int open_svr(const char* svr, int udp) { struct sockaddr_storage addr; socklen_t addrlen; int fd = -1; /* svr can be ip@port */ memset(&addr, 0, sizeof(addr)); if(!extstrtoaddr(svr, &addr, &addrlen)) { printf("fatal: bad server specs '%s'\n", svr); exit(1); } fd = socket(addr_is_ip6(&addr, addrlen)?PF_INET6:PF_INET, udp?SOCK_DGRAM:SOCK_STREAM, 0); if(fd == -1) { #ifndef USE_WINSOCK perror("socket() error"); #else printf("socket: %s\n", wsa_strerror(WSAGetLastError())); #endif exit(1); } if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) { #ifndef USE_WINSOCK perror("connect() error"); #else printf("connect: %s\n", wsa_strerror(WSAGetLastError())); #endif exit(1); } return fd; }
/** check interface strings */ static void interfacechecks(struct config_file* cfg) { struct sockaddr_storage a; socklen_t alen; int i, j; for(i=0; i<cfg->num_ifs; i++) { if(!extstrtoaddr(cfg->ifs[i], &a, &alen)) { fatal_exit("cannot parse interface specified as '%s'", cfg->ifs[i]); } for(j=0; j<cfg->num_ifs; j++) { if(i!=j && strcmp(cfg->ifs[i], cfg->ifs[j])==0) fatal_exit("interface: %s present twice, " "cannot bind same ports twice.", cfg->ifs[i]); } } for(i=0; i<cfg->num_out_ifs; i++) { if(!ipstrtoaddr(cfg->out_ifs[i], UNBOUND_DNS_PORT, &a, &alen)) { fatal_exit("cannot parse outgoing-interface " "specified as '%s'", cfg->out_ifs[i]); } for(j=0; j<cfg->num_out_ifs; j++) { if(i!=j && strcmp(cfg->out_ifs[i], cfg->out_ifs[j])==0) fatal_exit("outgoing-interface: %s present " "twice, cannot bind same ports twice.", cfg->out_ifs[i]); } } }
/** contact the server with TCP connect */ static int contact_server(const char* svr, struct config_file* cfg, int statuscmd) { struct sockaddr_storage addr; socklen_t addrlen; int fd; /* use svr or the first config entry */ if(!svr) { if(cfg->control_ifs) svr = cfg->control_ifs->str; else svr = "127.0.0.1"; /* config 0 addr (everything), means ask localhost */ if(strcmp(svr, "0.0.0.0") == 0) svr = "127.0.0.1"; else if(strcmp(svr, "::0") == 0 || strcmp(svr, "0::0") == 0 || strcmp(svr, "0::") == 0 || strcmp(svr, "::") == 0) svr = "::1"; } if(strchr(svr, '@')) { if(!extstrtoaddr(svr, &addr, &addrlen)) fatal_exit("could not parse IP@port: %s", svr); } else { if(!ipstrtoaddr(svr, cfg->control_port, &addr, &addrlen)) fatal_exit("could not parse IP: %s", svr); } fd = socket(addr_is_ip6(&addr, addrlen)?AF_INET6:AF_INET, SOCK_STREAM, 0); if(fd == -1) { #ifndef USE_WINSOCK fatal_exit("socket: %s", strerror(errno)); #else fatal_exit("socket: %s", wsa_strerror(WSAGetLastError())); #endif } if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) { log_addr(0, "address", &addr, addrlen); #ifndef USE_WINSOCK log_err("connect: %s", strerror(errno)); if(errno == ECONNREFUSED && statuscmd) { printf("unbound is stopped\n"); exit(3); } #else log_err("connect: %s", wsa_strerror(WSAGetLastError())); if(WSAGetLastError() == WSAECONNREFUSED && statuscmd) { printf("unbound is stopped\n"); exit(3); } #endif exit(1); } return fd; }
/** set stub server addresses */ static int read_stubs_addr(struct config_stub* s, struct delegpt* dp) { struct config_strlist* p; struct sockaddr_storage addr; socklen_t addrlen; for(p = s->addrs; p; p = p->next) { log_assert(p->str); if(!extstrtoaddr(p->str, &addr, &addrlen)) { log_err("cannot parse stub %s ip address: '%s'", s->name, p->str); return 0; } if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) { log_err("out of memory"); return 0; } } return 1; }
/** emit warnings for IP in hosts */ static void warn_hosts(const char* typ, struct config_stub* list) { struct sockaddr_storage a; socklen_t alen; struct config_stub* s; struct config_strlist* h; for(s=list; s; s=s->next) { for(h=s->hosts; h; h=h->next) { if(extstrtoaddr(h->str, &a, &alen)) { fprintf(stderr, "unbound-checkconf: warning:" " %s %s: \"%s\" is an IP%s address, " "and when looked up as a host name " "during use may not resolve.\n", s->name, typ, h->str, addr_is_ip6(&a, alen)?"6":"4"); } } } }
/** add hint to delegation hints */ static int ah(struct delegpt* dp, const char* sv, const char* ip) { struct sockaddr_storage addr; socklen_t addrlen; ldns_rdf* rdf = ldns_dname_new_frm_str(sv); if(!rdf) { log_err("could not parse %s", sv); return 0; } if(!delegpt_add_ns_mlc(dp, ldns_rdf_data(rdf), 0) || !extstrtoaddr(ip, &addr, &addrlen) || !delegpt_add_target_mlc(dp, ldns_rdf_data(rdf), ldns_rdf_size(rdf), &addr, addrlen, 0, 0)) { ldns_rdf_deep_free(rdf); return 0; } ldns_rdf_deep_free(rdf); return 1; }
/** add hint to delegation hints */ static int ah(struct delegpt* dp, const char* sv, const char* ip) { struct sockaddr_storage addr; socklen_t addrlen; size_t dname_len; uint8_t* dname = sldns_str2wire_dname(sv, &dname_len); if(!dname) { log_err("could not parse %s", sv); return 0; } if(!delegpt_add_ns_mlc(dp, dname, 0) || !extstrtoaddr(ip, &addr, &addrlen) || !delegpt_add_target_mlc(dp, dname, dname_len, &addr, addrlen, 0, 0)) { free(dname); return 0; } free(dname); return 1; }
int ub_ctx_set_fwd(struct ub_ctx* ctx, char* addr) { struct sockaddr_storage storage; socklen_t stlen; struct config_stub* s; char* dupl; lock_basic_lock(&ctx->cfglock); if(ctx->finalized) { lock_basic_unlock(&ctx->cfglock); errno=EINVAL; return UB_AFTERFINAL; } if(!addr) { /* disable fwd mode - the root stub should be first. */ if(ctx->env->cfg->forwards && strcmp(ctx->env->cfg->forwards->name, ".") == 0) { s = ctx->env->cfg->forwards; ctx->env->cfg->forwards = s->next; s->next = NULL; config_delstubs(s); } lock_basic_unlock(&ctx->cfglock); return UB_NOERROR; } lock_basic_unlock(&ctx->cfglock); /* check syntax for addr */ if(!extstrtoaddr(addr, &storage, &stlen)) { errno=EINVAL; return UB_SYNTAX; } /* it parses, add root stub in front of list */ lock_basic_lock(&ctx->cfglock); if(!ctx->env->cfg->forwards || strcmp(ctx->env->cfg->forwards->name, ".") != 0) { s = calloc(1, sizeof(*s)); if(!s) { lock_basic_unlock(&ctx->cfglock); errno=ENOMEM; return UB_NOMEM; } s->name = strdup("."); if(!s->name) { free(s); lock_basic_unlock(&ctx->cfglock); errno=ENOMEM; return UB_NOMEM; } s->next = ctx->env->cfg->forwards; ctx->env->cfg->forwards = s; } else { log_assert(ctx->env->cfg->forwards); s = ctx->env->cfg->forwards; } dupl = strdup(addr); if(!dupl) { lock_basic_unlock(&ctx->cfglock); errno=ENOMEM; return UB_NOMEM; } if(!cfg_strlist_insert(&s->addrs, dupl)) { free(dupl); lock_basic_unlock(&ctx->cfglock); errno=ENOMEM; return UB_NOMEM; } lock_basic_unlock(&ctx->cfglock); return UB_NOERROR; }
/** contact the server with TCP connect */ static int contact_server(const char* svr, struct config_file* cfg, int statuscmd) { struct sockaddr_storage addr; socklen_t addrlen; int addrfamily = 0; int fd; /* use svr or the first config entry */ if(!svr) { if(cfg->control_ifs) svr = cfg->control_ifs->str; else svr = "127.0.0.1"; /* config 0 addr (everything), means ask localhost */ if(strcmp(svr, "0.0.0.0") == 0) svr = "127.0.0.1"; else if(strcmp(svr, "::0") == 0 || strcmp(svr, "0::0") == 0 || strcmp(svr, "0::") == 0 || strcmp(svr, "::") == 0) svr = "::1"; } if(strchr(svr, '@')) { if(!extstrtoaddr(svr, &addr, &addrlen)) fatal_exit("could not parse IP@port: %s", svr); #ifdef HAVE_SYS_UN_H } else if(svr[0] == '/') { struct sockaddr_un* usock = (struct sockaddr_un *) &addr; usock->sun_family = AF_LOCAL; #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN usock->sun_len = (socklen_t)sizeof(usock); #endif (void)strlcpy(usock->sun_path, svr, sizeof(usock->sun_path)); addrlen = (socklen_t)sizeof(struct sockaddr_un); addrfamily = AF_LOCAL; #endif } else { if(!ipstrtoaddr(svr, cfg->control_port, &addr, &addrlen)) fatal_exit("could not parse IP: %s", svr); } if(addrfamily == 0) addrfamily = addr_is_ip6(&addr, addrlen)?AF_INET6:AF_INET; fd = socket(addrfamily, SOCK_STREAM, 0); if(fd == -1) { #ifndef USE_WINSOCK fatal_exit("socket: %s", strerror(errno)); #else fatal_exit("socket: %s", wsa_strerror(WSAGetLastError())); #endif } if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) { #ifndef USE_WINSOCK log_err_addr("connect", strerror(errno), &addr, addrlen); if(errno == ECONNREFUSED && statuscmd) { printf("unbound is stopped\n"); exit(3); } #else log_err_addr("connect", wsa_strerror(WSAGetLastError()), &addr, addrlen); if(WSAGetLastError() == WSAECONNREFUSED && statuscmd) { printf("unbound is stopped\n"); exit(3); } #endif exit(1); } return fd; }
/** * Read a replay moment 'STEP' from file. * @param remain: Rest of line (after STEP keyword). * @param in: file to read from. * @param name: name to print in errors. * @param lineno: incremented as lines are read. * @param ttl: for readentry * @param or: for readentry * @param prev: for readentry * @return: range object to add to list, or NULL on error. */ static struct replay_moment* replay_moment_read(char* remain, FILE* in, const char* name, int* lineno, uint32_t* ttl, ldns_rdf** or, ldns_rdf** prev) { struct replay_moment* mom = (struct replay_moment*)malloc( sizeof(struct replay_moment)); int skip = 0; int readentry = 0; if(!mom) return NULL; memset(mom, 0, sizeof(*mom)); if(sscanf(remain, " %d%n", &mom->time_step, &skip) != 1) { log_err("%d: cannot read number: %s", *lineno, remain); free(mom); return NULL; } remain += skip; while(isspace((int)*remain)) remain++; if(parse_keyword(&remain, "NOTHING")) { mom->evt_type = repevt_nothing; } else if(parse_keyword(&remain, "QUERY")) { mom->evt_type = repevt_front_query; readentry = 1; if(!extstrtoaddr("127.0.0.1", &mom->addr, &mom->addrlen)) fatal_exit("internal error"); } else if(parse_keyword(&remain, "CHECK_ANSWER")) { mom->evt_type = repevt_front_reply; readentry = 1; } else if(parse_keyword(&remain, "CHECK_OUT_QUERY")) { mom->evt_type = repevt_back_query; readentry = 1; } else if(parse_keyword(&remain, "REPLY")) { mom->evt_type = repevt_back_reply; readentry = 1; } else if(parse_keyword(&remain, "TIMEOUT")) { mom->evt_type = repevt_timeout; } else if(parse_keyword(&remain, "TIME_PASSES")) { mom->evt_type = repevt_time_passes; while(isspace((int)*remain)) remain++; if(parse_keyword(&remain, "EVAL")) { while(isspace((int)*remain)) remain++; mom->string = strdup(remain); if(!mom->string) fatal_exit("out of memory"); if(strlen(mom->string)>0) mom->string[strlen(mom->string)-1]=0; remain += strlen(mom->string); } } else if(parse_keyword(&remain, "CHECK_AUTOTRUST")) { mom->evt_type = repevt_autotrust_check; while(isspace((int)*remain)) remain++; if(strlen(remain)>0 && remain[strlen(remain)-1]=='\n') remain[strlen(remain)-1] = 0; mom->autotrust_id = strdup(remain); if(!mom->autotrust_id) fatal_exit("out of memory"); read_file_content(in, lineno, mom); } else if(parse_keyword(&remain, "ERROR")) { mom->evt_type = repevt_error; } else if(parse_keyword(&remain, "TRAFFIC")) { mom->evt_type = repevt_traffic; } else if(parse_keyword(&remain, "ASSIGN")) { mom->evt_type = repevt_assign; read_assign_step(remain, mom); } else if(parse_keyword(&remain, "INFRA_RTT")) { char *s, *m; mom->evt_type = repevt_infra_rtt; while(isspace((int)*remain)) remain++; s = remain; remain = strchr(s, ' '); if(!remain) fatal_exit("expected three args for INFRA_RTT"); remain[0] = 0; remain++; while(isspace((int)*remain)) remain++; m = strchr(remain, ' '); if(!m) fatal_exit("expected three args for INFRA_RTT"); m[0] = 0; m++; while(isspace((int)*m)) m++; if(!extstrtoaddr(s, &mom->addr, &mom->addrlen)) fatal_exit("bad infra_rtt address %s", s); if(strlen(m)>0 && m[strlen(m)-1]=='\n') m[strlen(m)-1] = 0; mom->variable = strdup(remain); mom->string = strdup(m); if(!mom->string) fatal_exit("out of memory"); if(!mom->variable) fatal_exit("out of memory"); } else { log_err("%d: unknown event type %s", *lineno, remain); free(mom); return NULL; } while(isspace((int)*remain)) remain++; if(parse_keyword(&remain, "ADDRESS")) { while(isspace((int)*remain)) remain++; if(strlen(remain) > 0) /* remove \n */ remain[strlen(remain)-1] = 0; if(!extstrtoaddr(remain, &mom->addr, &mom->addrlen)) { log_err("line %d: could not parse ADDRESS: %s", *lineno, remain); free(mom); return NULL; } } if(parse_keyword(&remain, "ELAPSE")) { double sec; errno = 0; sec = strtod(remain, &remain); if(sec == 0. && errno != 0) { log_err("line %d: could not parse ELAPSE: %s (%s)", *lineno, remain, strerror(errno)); free(mom); return NULL; } #ifndef S_SPLINT_S mom->elapse.tv_sec = (int)sec; mom->elapse.tv_usec = (int)((sec - (double)mom->elapse.tv_sec) *1000000. + 0.5); #endif } if(readentry) { mom->match = read_entry(in, name, lineno, ttl, or, prev, 1); if(!mom->match) { free(mom); return NULL; } } return mom; }
/** * Read a range from file. * @param remain: Rest of line (after RANGE keyword). * @param in: file to read from. * @param name: name to print in errors. * @param lineno: incremented as lines are read. * @param line: line buffer. * @param ttl: for readentry * @param or: for readentry * @param prev: for readentry * @return: range object to add to list, or NULL on error. */ static struct replay_range* replay_range_read(char* remain, FILE* in, const char* name, int* lineno, char* line, uint32_t* ttl, ldns_rdf** or, ldns_rdf** prev) { struct replay_range* rng = (struct replay_range*)malloc( sizeof(struct replay_range)); off_t pos; char *parse; struct entry* entry, *last = NULL; if(!rng) return NULL; memset(rng, 0, sizeof(*rng)); /* read time range */ if(sscanf(remain, " %d %d", &rng->start_step, &rng->end_step)!=2) { log_err("Could not read time range: %s", line); free(rng); return NULL; } /* read entries */ pos = ftello(in); while(fgets(line, MAX_LINE_LEN-1, in)) { (*lineno)++; parse = line; while(isspace((int)*parse)) parse++; if(!*parse || *parse == ';') { pos = ftello(in); continue; } if(parse_keyword(&parse, "ADDRESS")) { while(isspace((int)*parse)) parse++; strip_end_white(parse); if(!extstrtoaddr(parse, &rng->addr, &rng->addrlen)) { log_err("Line %d: could not read ADDRESS: %s", *lineno, parse); free(rng); return NULL; } pos = ftello(in); continue; } if(parse_keyword(&parse, "RANGE_END")) { return rng; } /* set position before line; read entry */ (*lineno)--; fseeko(in, pos, SEEK_SET); entry = read_entry(in, name, lineno, ttl, or, prev, 1); if(!entry) fatal_exit("%d: bad entry", *lineno); entry->next = NULL; if(last) last->next = entry; else rng->match = entry; last = entry; pos = ftello(in); } replay_range_delete(rng); return NULL; }
int ub_ctx_set_stub(struct ub_ctx* ctx, const char* zone, const char* addr, int isprime) { char* a; struct config_stub **prev, *elem; /* check syntax for zone name */ if(zone) { uint8_t* nm; int nmlabs; size_t nmlen; if(!parse_dname(zone, &nm, &nmlen, &nmlabs)) { errno=EINVAL; return UB_SYNTAX; } free(nm); } else { zone = "."; } /* check syntax for addr (if not NULL) */ if(addr) { struct sockaddr_storage storage; socklen_t stlen; if(!extstrtoaddr(addr, &storage, &stlen)) { errno=EINVAL; return UB_SYNTAX; } } lock_basic_lock(&ctx->cfglock); if(ctx->finalized) { lock_basic_unlock(&ctx->cfglock); errno=EINVAL; return UB_AFTERFINAL; } /* arguments all right, now find or add the stub */ prev = &ctx->env->cfg->stubs; elem = cfg_stub_find(&prev, zone); if(!elem && !addr) { /* not found and we want to delete, nothing to do */ lock_basic_unlock(&ctx->cfglock); return UB_NOERROR; } else if(elem && !addr) { /* found, and we want to delete */ *prev = elem->next; config_delstub(elem); lock_basic_unlock(&ctx->cfglock); return UB_NOERROR; } else if(!elem) { /* not found, create the stub entry */ elem=(struct config_stub*)calloc(1, sizeof(struct config_stub)); if(elem) elem->name = strdup(zone); if(!elem || !elem->name) { free(elem); lock_basic_unlock(&ctx->cfglock); errno = ENOMEM; return UB_NOMEM; } elem->next = ctx->env->cfg->stubs; ctx->env->cfg->stubs = elem; } /* add the address to the list and set settings */ elem->isprime = isprime; a = strdup(addr); if(!a) { lock_basic_unlock(&ctx->cfglock); errno = ENOMEM; return UB_NOMEM; } if(!cfg_strlist_insert(&elem->addrs, a)) { lock_basic_unlock(&ctx->cfglock); errno = ENOMEM; return UB_NOMEM; } lock_basic_unlock(&ctx->cfglock); return UB_NOERROR; }
/** delayer main service routine */ static void service(const char* bind_str, int bindport, const char* serv_str, size_t memsize, int delay_msec) { struct sockaddr_storage bind_addr, srv_addr; socklen_t bind_len, srv_len; struct ringbuf* ring = ring_create(memsize); struct timeval delay, reuse; sldns_buffer* pkt; int i, s, listen_s; #ifndef S_SPLINT_S delay.tv_sec = delay_msec / 1000; delay.tv_usec = (delay_msec % 1000)*1000; #endif reuse = delay; /* reuse is max(4*delay, 1 second) */ dl_tv_add(&reuse, &delay); dl_tv_add(&reuse, &delay); dl_tv_add(&reuse, &delay); if(reuse.tv_sec == 0) reuse.tv_sec = 1; if(!extstrtoaddr(serv_str, &srv_addr, &srv_len)) { printf("cannot parse forward address: %s\n", serv_str); exit(1); } pkt = sldns_buffer_new(65535); if(!pkt) fatal_exit("out of memory"); if( signal(SIGINT, delayer_sigh) == SIG_ERR || #ifdef SIGHUP signal(SIGHUP, delayer_sigh) == SIG_ERR || #endif #ifdef SIGQUIT signal(SIGQUIT, delayer_sigh) == SIG_ERR || #endif #ifdef SIGBREAK signal(SIGBREAK, delayer_sigh) == SIG_ERR || #endif #ifdef SIGALRM signal(SIGALRM, delayer_sigh) == SIG_ERR || #endif signal(SIGTERM, delayer_sigh) == SIG_ERR) fatal_exit("could not bind to signal"); /* bind UDP port */ if((s = socket(str_is_ip6(bind_str)?AF_INET6:AF_INET, SOCK_DGRAM, 0)) == -1) { #ifndef USE_WINSOCK fatal_exit("socket: %s", strerror(errno)); #else fatal_exit("socket: %s", wsa_strerror(WSAGetLastError())); #endif } i=0; if(bindport == 0) { bindport = 1024 + random()%64000; i = 100; } while(1) { if(!ipstrtoaddr(bind_str, bindport, &bind_addr, &bind_len)) { printf("cannot parse listen address: %s\n", bind_str); exit(1); } if(bind(s, (struct sockaddr*)&bind_addr, bind_len) == -1) { #ifndef USE_WINSOCK log_err("bind: %s", strerror(errno)); #else log_err("bind: %s", wsa_strerror(WSAGetLastError())); #endif if(i--==0) fatal_exit("cannot bind any port"); bindport = 1024 + random()%64000; } else break; } fd_set_nonblock(s); /* and TCP port */ if((listen_s = socket(str_is_ip6(bind_str)?AF_INET6:AF_INET, SOCK_STREAM, 0)) == -1) { #ifndef USE_WINSOCK fatal_exit("tcp socket: %s", strerror(errno)); #else fatal_exit("tcp socket: %s", wsa_strerror(WSAGetLastError())); #endif } #ifdef SO_REUSEADDR if(1) { int on = 1; if(setsockopt(listen_s, SOL_SOCKET, SO_REUSEADDR, (void*)&on, (socklen_t)sizeof(on)) < 0) #ifndef USE_WINSOCK fatal_exit("setsockopt(.. SO_REUSEADDR ..) failed: %s", strerror(errno)); #else fatal_exit("setsockopt(.. SO_REUSEADDR ..) failed: %s", wsa_strerror(WSAGetLastError())); #endif } #endif if(bind(listen_s, (struct sockaddr*)&bind_addr, bind_len) == -1) { #ifndef USE_WINSOCK fatal_exit("tcp bind: %s", strerror(errno)); #else fatal_exit("tcp bind: %s", wsa_strerror(WSAGetLastError())); #endif } if(listen(listen_s, 5) == -1) { #ifndef USE_WINSOCK fatal_exit("tcp listen: %s", strerror(errno)); #else fatal_exit("tcp listen: %s", wsa_strerror(WSAGetLastError())); #endif } fd_set_nonblock(listen_s); printf("listening on port: %d\n", bindport); /* process loop */ do_quit = 0; service_loop(s, listen_s, ring, &delay, &reuse, &srv_addr, srv_len, pkt); /* cleanup */ verbose(1, "cleanup"); #ifndef USE_WINSOCK close(s); close(listen_s); #else closesocket(s); closesocket(listen_s); #endif sldns_buffer_free(pkt); ring_delete(ring); }
/** main program for perf */ int main(int argc, char* argv[]) { char* nm = argv[0]; int c; struct perfinfo info; #ifdef USE_WINSOCK int r; WSADATA wsa_data; #endif /* defaults */ memset(&info, 0, sizeof(info)); info.io_num = 16; log_init(NULL, 0, NULL); log_ident_set("perf"); checklock_start(); #ifdef USE_WINSOCK if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0) fatal_exit("WSAStartup failed: %s", wsa_strerror(r)); #endif info.buf = sldns_buffer_new(65553); if(!info.buf) fatal_exit("out of memory"); /* parse the options */ while( (c=getopt(argc, argv, "d:ha:f:q")) != -1) { switch(c) { case 'q': info.quiet = 1; break; case 'd': if(atoi(optarg)==0 && strcmp(optarg, "0")!=0) { printf("-d not a number %s", optarg); return 1; } info.duration = atoi(optarg); break; case 'a': qlist_add_line(&info, optarg, 0); break; case 'f': qlist_read_file(&info, optarg); break; case '?': case 'h': default: usage(nm); } } argc -= optind; argv += optind; if(argc != 1) { printf("error: pass server IP address on commandline.\n"); usage(nm); } if(!extstrtoaddr(argv[0], &info.dest, &info.destlen)) { printf("Could not parse ip: %s\n", argv[0]); return 1; } if(info.qlist_size == 0) { printf("No queries to make, use -f or -a.\n"); return 1; } /* do the performance test */ perfmain(&info); sldns_buffer_free(info.buf); #ifdef USE_WINSOCK WSACleanup(); #endif checklock_stop(); return 0; }