Пример #1
0
int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr,
        socklen_t* addrlen, int* net)
{
	char buf[64];
	char* s;
	*net = (str_is_ip6(str)?128:32);
	if((s=strchr(str, '/'))) {
		if(atoi(s+1) > *net) {
			log_err("netblock too large: %s", str);
			return 0;
		}
		*net = atoi(s+1);
		if(*net == 0 && strcmp(s+1, "0") != 0) {
			log_err("cannot parse netblock: '%s'", str);
			return 0;
		}
		strlcpy(buf, str, sizeof(buf));
		s = strchr(buf, '/');
		if(s) *s = 0;
		s = buf;
	}
	if(!ipstrtoaddr(s?s:str, port, addr, addrlen)) {
		log_err("cannot parse ip address: '%s'", str);
		return 0;
	}
	if(s) {
		addr_mask(addr, *addrlen, *net);
	}
	return 1;
}
Пример #2
0
int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr,
        socklen_t* addrlen, int* net)
{
	char* s = NULL;
	*net = (str_is_ip6(str)?128:32);
	if((s=strchr(str, '/'))) {
		if(atoi(s+1) > *net) {
			log_err("netblock too large: %s", str);
			return 0;
		}
		*net = atoi(s+1);
		if(*net == 0 && strcmp(s+1, "0") != 0) {
			log_err("cannot parse netblock: '%s'", str);
			return 0;
		}
		if(!(s = strdup(str))) {
			log_err("out of memory");
			return 0;
		}
		*strchr(s, '/') = '\0';
	}
	if(!ipstrtoaddr(s?s:str, port, addr, addrlen)) {
		free(s);
		log_err("cannot parse ip address: '%s'", str);
		return 0;
	}
	if(s) {
		free(s);
		addr_mask(addr, *addrlen, *net);
	}
	return 1;
}
Пример #3
0
int 
ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr,
	socklen_t* addrlen)
{
	uint16_t p;
	if(!ip) return 0;
	p = (uint16_t) port;
	if(str_is_ip6(ip)) {
		char buf[MAX_ADDR_STRLEN];
		char* s;
		struct sockaddr_in6* sa = (struct sockaddr_in6*)addr;
		*addrlen = (socklen_t)sizeof(struct sockaddr_in6);
		memset(sa, 0, *addrlen);
		sa->sin6_family = AF_INET6;
		sa->sin6_port = (in_port_t)htons(p);
		if((s=strchr(ip, '%'))) { /* ip6%interface, rfc 4007 */
			if(s-ip >= MAX_ADDR_STRLEN)
				return 0;
			(void)strlcpy(buf, ip, sizeof(buf));
			buf[s-ip]=0;
			sa->sin6_scope_id = (uint32_t)atoi(s+1);
			ip = buf;
		}
		if(inet_pton((int)sa->sin6_family, ip, &sa->sin6_addr) <= 0) {
			return 0;
		}
	} else { /* ip4 */
		struct sockaddr_in* sa = (struct sockaddr_in*)addr;
		*addrlen = (socklen_t)sizeof(struct sockaddr_in);
		memset(sa, 0, *addrlen);
		sa->sin_family = AF_INET;
		sa->sin_port = (in_port_t)htons(p);
		if(inet_pton((int)sa->sin_family, ip, &sa->sin_addr) <= 0) {
			return 0;
		}
	}
	return 1;
}
Пример #4
0
int
ub_ctx_hosts(struct ub_ctx* ctx, char* fname)
{
    FILE* in;
    char buf[1024], ldata[1024];
    char* parse, *addr, *name, *ins;
    lock_basic_lock(&ctx->cfglock);
    if(ctx->finalized) {
        lock_basic_unlock(&ctx->cfglock);
        errno=EINVAL;
        return UB_AFTERFINAL;
    }
    lock_basic_unlock(&ctx->cfglock);
    if(fname == NULL) {
#if defined(UB_ON_WINDOWS) && defined(HAVE_WINDOWS_H)
        /*
         * If this is Windows NT/XP/2K it's in
         * %WINDIR%\system32\drivers\etc\hosts.
         * If this is Windows 95/98/Me it's in %WINDIR%\hosts.
         */
        name = getenv("WINDIR");
        if (name != NULL) {
            int retval=0;
            snprintf(buf, sizeof(buf), "%s%s", name,
                     "\\system32\\drivers\\etc\\hosts");
            if((retval=ub_ctx_hosts(ctx, buf)) !=0 ) {
                snprintf(buf, sizeof(buf), "%s%s", name,
                         "\\hosts");
                retval=ub_ctx_hosts(ctx, buf);
            }
            free(name);
            return retval;
        }
        return UB_READFILE;
#else
        fname = "/etc/hosts";
#endif /* WIN32 */
    }
    in = fopen(fname, "r");
    if(!in) {
        /* error in errno! perror(fname) */
        return UB_READFILE;
    }
    while(fgets(buf, (int)sizeof(buf), in)) {
        buf[sizeof(buf)-1] = 0;
        parse=buf;
        while(*parse == ' ' || *parse == '\t')
            parse++;
        if(*parse == '#')
            continue; /* skip comment */
        /* format: <addr> spaces <name> spaces <name> ... */
        addr = parse;
        /* skip addr */
        while(isxdigit(*parse) || *parse == '.' || *parse == ':')
            parse++;
        if(*parse == '\n' || *parse == 0)
            continue;
        if(*parse == '%')
            continue; /* ignore macOSX fe80::1%lo0 localhost */
        if(*parse != ' ' && *parse != '\t') {
            /* must have whitespace after address */
            fclose(in);
            errno=EINVAL;
            return UB_SYNTAX;
        }
        *parse++ = 0; /* end delimiter for addr ... */
        /* go to names and add them */
        while(*parse) {
            while(*parse == ' ' || *parse == '\t' || *parse=='\n')
                parse++;
            if(*parse == 0 || *parse == '#')
                break;
            /* skip name, allows (too) many printable characters */
            name = parse;
            while('!' <= *parse && *parse <= '~')
                parse++;
            if(*parse)
                *parse++ = 0; /* end delimiter for name */
            snprintf(ldata, sizeof(ldata), "%s %s %s",
                     name, str_is_ip6(addr)?"AAAA":"A", addr);
            ins = strdup(ldata);
            if(!ins) {
                /* out of memory */
                fclose(in);
                errno=ENOMEM;
                return UB_NOMEM;
            }
            lock_basic_lock(&ctx->cfglock);
            if(!cfg_strlist_insert(&ctx->env->cfg->local_data,
                                   ins)) {
                lock_basic_unlock(&ctx->cfglock);
                fclose(in);
                free(ins);
                errno=ENOMEM;
                return UB_NOMEM;
            }
            lock_basic_unlock(&ctx->cfglock);
        }
    }
    fclose(in);
    return UB_NOERROR;
}
Пример #5
0
struct listen_port* 
listening_ports_open(struct config_file* cfg)
{
	struct listen_port* list = NULL;
	struct addrinfo hints;
	int i, do_ip4, do_ip6;
	int do_tcp, do_auto;
	char portbuf[32];
	snprintf(portbuf, sizeof(portbuf), "%d", cfg->port);
	do_ip4 = cfg->do_ip4;
	do_ip6 = cfg->do_ip6;
	do_tcp = cfg->do_tcp;
	do_auto = cfg->if_automatic && cfg->do_udp;
	if(cfg->incoming_num_tcp == 0)
		do_tcp = 0;

	/* getaddrinfo */
	memset(&hints, 0, sizeof(hints));
	hints.ai_flags = AI_PASSIVE;
	/* no name lookups on our listening ports */
	if(cfg->num_ifs > 0)
		hints.ai_flags |= AI_NUMERICHOST;
	hints.ai_family = AF_UNSPEC;
#ifndef INET6
	do_ip6 = 0;
#endif
	if(!do_ip4 && !do_ip6) {
		return NULL;
	}
	/* create ip4 and ip6 ports so that return addresses are nice. */
	if(do_auto || cfg->num_ifs == 0) {
		if(do_ip6) {
			hints.ai_family = AF_INET6;
			if(!ports_create_if(do_auto?"::0":"::1", 
				do_auto, cfg->do_udp, do_tcp, 
				&hints, portbuf, &list,
				cfg->so_rcvbuf, cfg->so_sndbuf,
				cfg->ssl_port)) {
				listening_ports_free(list);
				return NULL;
			}
		}
		if(do_ip4) {
			hints.ai_family = AF_INET;
			if(!ports_create_if(do_auto?"0.0.0.0":"127.0.0.1", 
				do_auto, cfg->do_udp, do_tcp, 
				&hints, portbuf, &list,
				cfg->so_rcvbuf, cfg->so_sndbuf,
				cfg->ssl_port)) {
				listening_ports_free(list);
				return NULL;
			}
		}
	} else for(i = 0; i<cfg->num_ifs; i++) {
		if(str_is_ip6(cfg->ifs[i])) {
			if(!do_ip6)
				continue;
			hints.ai_family = AF_INET6;
			if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp, 
				do_tcp, &hints, portbuf, &list, 
				cfg->so_rcvbuf, cfg->so_sndbuf,
				cfg->ssl_port)) {
				listening_ports_free(list);
				return NULL;
			}
		} else {
			if(!do_ip4)
				continue;
			hints.ai_family = AF_INET;
			if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp, 
				do_tcp, &hints, portbuf, &list, 
				cfg->so_rcvbuf, cfg->so_sndbuf,
				cfg->ssl_port)) {
				listening_ports_free(list);
				return NULL;
			}
		}
	}
	return list;
}
Пример #6
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);
}