}
else if (interpolated_path && saw_extended_args) {
struct strbuf expanded_path = STRBUF_INIT;
- struct strbuf_expand_dict_entry dict[] = {
- { "H", hostname },
- { "CH", canon_hostname },
- { "IP", ip_address },
- { "P", tcp_port },
- { "D", directory },
- { "%", "%" },
- { NULL }
- };
-
+ struct strbuf_expand_dict_entry dict[6];
+
+ dict[0].placeholder = "H"; dict[0].value = hostname;
+ dict[1].placeholder = "CH"; dict[1].value = canon_hostname;
+ dict[2].placeholder = "IP"; dict[2].value = ip_address;
+ dict[3].placeholder = "P"; dict[3].value = tcp_port;
+ dict[4].placeholder = "D"; dict[4].value = directory;
+ dict[5].placeholder = NULL; dict[5].value = NULL;
if (*dir != '/') {
/* Allow only absolute */
logerror("'%s': Non-absolute path denied (interpolated-path active)", dir);
{
/* Timeout as string */
char timeout_buf[64];
- const char *argv[] = { "upload-pack", "--strict", timeout_buf, ".", NULL };
+ const char *argv[] = { "upload-pack", "--strict", NULL, ".", NULL };
+
+ argv[2] = timeout_buf;
snprintf(timeout_buf, sizeof timeout_buf, "--timeout=%u", timeout);
return run_service_command(argv);
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.
*/
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);
}
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;
{
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;
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;
}