diff options
Diffstat (limited to 'daemon.c')
| -rw-r--r-- | daemon.c | 66 | 
1 files changed, 53 insertions, 13 deletions
| @@ -147,7 +147,6 @@ static char *path_ok(char *directory)  			{ "IP", ip_address },  			{ "P", tcp_port },  			{ "D", directory }, -			{ "%", "%" },  			{ NULL }  		}; @@ -400,6 +399,33 @@ static char *xstrdup_tolower(const char *str)  	return dup;  } +static void parse_host_and_port(char *hostport, char **host, +	char **port) +{ +	if (*hostport == '[') { +		char *end; + +		end = strchr(hostport, ']'); +		if (!end) +			die("Invalid request ('[' without ']')"); +		*end = '\0'; +		*host = hostport + 1; +		if (!end[1]) +			*port = NULL; +		else if (end[1] == ':') +			*port = end + 2; +		else +			die("Garbage after end of host part"); +	} else { +		*host = hostport; +		*port = strrchr(hostport, ':'); +		if (*port) { +			**port = '\0'; +			++*port; +		} +	} +} +  /*   * Read the host as supplied by the client connection.   */ @@ -416,11 +442,10 @@ static void parse_host_arg(char *extra_args, int buflen)  			vallen = strlen(val) + 1;  			if (*val) {  				/* Split <host>:<port> at colon. */ -				char *host = val; -				char *port = strrchr(host, ':'); +				char *host; +				char *port; +				parse_host_and_port(val, &host, &port);  				if (port) { -					*port = 0; -					port++;  					free(tcp_port);  					tcp_port = xstrdup(port);  				} @@ -562,6 +587,27 @@ static int execute(struct sockaddr *addr)  	return -1;  } +static int addrcmp(const struct sockaddr_storage *s1, +    const struct sockaddr_storage *s2) +{ +	const struct sockaddr *sa1 = (const struct sockaddr*) s1; +	const struct sockaddr *sa2 = (const struct sockaddr*) s2; + +	if (sa1->sa_family != sa2->sa_family) +		return sa1->sa_family - sa2->sa_family; +	if (sa1->sa_family == AF_INET) +		return memcmp(&((struct sockaddr_in *)s1)->sin_addr, +		    &((struct sockaddr_in *)s2)->sin_addr, +		    sizeof(struct in_addr)); +#ifndef NO_IPV6 +	if (sa1->sa_family == AF_INET6) +		return memcmp(&((struct sockaddr_in6 *)s1)->sin6_addr, +		    &((struct sockaddr_in6 *)s2)->sin6_addr, +		    sizeof(struct in6_addr)); +#endif +	return 0; +} +  static int max_connections = 32;  static unsigned int live_children; @@ -576,17 +622,12 @@ static void add_child(pid_t pid, struct sockaddr *addr, int addrlen)  {  	struct child *newborn, **cradle; -	/* -	 * This must be xcalloc() -- we'll compare the whole sockaddr_storage -	 * but individual address may be shorter. -	 */  	newborn = xcalloc(1, sizeof(*newborn));  	live_children++;  	newborn->pid = pid;  	memcpy(&newborn->address, addr, addrlen);  	for (cradle = &firstborn; *cradle; cradle = &(*cradle)->next) -		if (!memcmp(&(*cradle)->address, &newborn->address, -			    sizeof(newborn->address))) +		if (!addrcmp(&(*cradle)->address, &newborn->address))  			break;  	newborn->next = *cradle;  	*cradle = newborn; @@ -619,8 +660,7 @@ static void kill_some_child(void)  		return;  	for (; (next = blanket->next); blanket = next) -		if (!memcmp(&blanket->address, &next->address, -			    sizeof(next->address))) { +		if (!addrcmp(&blanket->address, &next->address)) {  			kill(blanket->pid, SIGTERM);  			break;  		} | 
