예제 #1
0
파일: remote.c 프로젝트: RS-liuyang/rsdns
/** 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;
}
예제 #2
0
/** 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;
}
예제 #3
0
/** 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]);
		}
	}
}
예제 #4
0
/** 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;
}
예제 #5
0
/** 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;
}
예제 #6
0
/** 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");
			}
		}
	}
}
예제 #7
0
/** 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;
}
예제 #8
0
/** 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;
}
예제 #9
0
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;
}
예제 #10
0
/** 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;
}
예제 #11
0
파일: replay.c 프로젝트: mir-ror/unbound
/** 
 * 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;
}
예제 #12
0
파일: replay.c 프로젝트: mir-ror/unbound
/** 
 * 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;
}
예제 #13
0
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;
}
예제 #14
0
/** 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);
}
예제 #15
0
파일: perf.c 프로젝트: CryptArc/bitmonero
/** 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;
}