daemon: deglobalize hostname information

Move the variables related to the client-supplied hostname into its own struct, let execute() own an instance of that instead of storing the information in global variables and pass the struct to any function that needs to access it as a parameter. The lifetime of the variables is easier to see this way. Allocated memory is released within execute(). The strbufs don't have to be reset anymore because they are written to only once at most: parse_host_arg() is only called once by execute() and lookup_hostname() guards against being called twice using hostname_lookup_done. Signed-off-by: Rene Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

René Scharfe committed Mar 7, 2015 at 11:50 UTC 01cec54e135c6c70bf6e1e197590749076e7cdfd
1 file changed +74 -59
daemon.c
+74 -59
@@ -43,9 +43,6 @@ static const char *base_path;
43 static const char *interpolated_path;
44 static int base_path_relaxed;
45
46 -/* Flag indicating client sent extra args. */
47 -static int saw_extended_args;
48 -
46 /* If defined, ~user notation is allowed and the string is inserted
47 * after ~user/. E.g. a request to git://host/~alice/frotz would
48 * go to /home/alice/pub_git/frotz with --user-path=pub_git.
@@ -56,25 +53,27 @@ static const char *user_path;
53 static unsigned int timeout;
54 static unsigned int init_timeout;
55
59 -static struct strbuf hostname = STRBUF_INIT;
60 -static struct strbuf canon_hostname = STRBUF_INIT;
61 -static struct strbuf ip_address = STRBUF_INIT;
62 -static struct strbuf tcp_port = STRBUF_INIT;
63 -
64 -static int hostname_lookup_done;
56 +struct hostinfo {
57 + struct strbuf hostname;
58 + struct strbuf canon_hostname;
59 + struct strbuf ip_address;
60 + struct strbuf tcp_port;
61 + unsigned int hostname_lookup_done:1;
62 + unsigned int saw_extended_args:1;
63 +};
64
66 -static void lookup_hostname(void);
65 +static void lookup_hostname(struct hostinfo *hi);
66
68 -static const char *get_canon_hostname(void)
67 +static const char *get_canon_hostname(struct hostinfo *hi)
68 {
70 - lookup_hostname();
71 - return canon_hostname.buf;
69 + lookup_hostname(hi);
70 + return hi->canon_hostname.buf;
71 }
72
74 -static const char *get_ip_address(void)
73 +static const char *get_ip_address(struct hostinfo *hi)
74 {
76 - lookup_hostname();
77 - return ip_address.buf;
75 + lookup_hostname(hi);
76 + return hi->ip_address.buf;
77 }
78
79 static void logreport(int priority, const char *err, va_list params)
@@ -124,30 +123,32 @@ static void NORETURN daemon_die(const char *err, va_list params)
123
124 struct expand_path_context {
125 const char *directory;
126 + struct hostinfo *hostinfo;
127 };
128
129 static size_t expand_path(struct strbuf *sb, const char *placeholder, void *ctx)
130 {
131 struct expand_path_context *context = ctx;
132 + struct hostinfo *hi = context->hostinfo;
133
134 switch (placeholder[0]) {
135 case 'H':
135 - strbuf_addbuf(sb, &hostname);
136 + strbuf_addbuf(sb, &hi->hostname);
137 return 1;
138 case 'C':
139 if (placeholder[1] == 'H') {
139 - strbuf_addstr(sb, get_canon_hostname());
140 + strbuf_addstr(sb, get_canon_hostname(hi));
141 return 2;
142 }
143 break;
144 case 'I':
145 if (placeholder[1] == 'P') {
145 - strbuf_addstr(sb, get_ip_address());
146 + strbuf_addstr(sb, get_ip_address(hi));
147 return 2;
148 }
149 break;
150 case 'P':
150 - strbuf_addbuf(sb, &tcp_port);
151 + strbuf_addbuf(sb, &hi->tcp_port);
152 return 1;
153 case 'D':
154 strbuf_addstr(sb, context->directory);
@@ -156,7 +157,7 @@ static size_t expand_path(struct strbuf *sb, const char *placeholder, void *ctx)
157 return 0;
158 }
159
159 -static const char *path_ok(const char *directory)
160 +static const char *path_ok(const char *directory, struct hostinfo *hi)
161 {
162 static char rpath[PATH_MAX];
163 static char interp_path[PATH_MAX];
@@ -192,11 +193,12 @@ static const char *path_ok(const char *directory)
193 dir = rpath;
194 }
195 }
195 - else if (interpolated_path && saw_extended_args) {
196 + else if (interpolated_path && hi->saw_extended_args) {
197 struct strbuf expanded_path = STRBUF_INIT;
198 struct expand_path_context context;
199
200 context.directory = directory;
201 + context.hostinfo = hi;
202
203 if (*dir != '/') {
204 /* Allow only absolute */
@@ -286,7 +288,8 @@ static int daemon_error(const char *dir, const char *msg)
288
289 static const char *access_hook;
290
289 -static int run_access_hook(struct daemon_service *service, const char *dir, const char *path)
291 +static int run_access_hook(struct daemon_service *service, const char *dir,
292 + const char *path, struct hostinfo *hi)
293 {
294 struct child_process child = CHILD_PROCESS_INIT;
295 struct strbuf buf = STRBUF_INIT;
@@ -298,10 +301,10 @@ static int run_access_hook(struct daemon_service *service, const char *dir, cons
301 *arg++ = access_hook;
302 *arg++ = service->name;
303 *arg++ = path;
301 - *arg++ = hostname.buf;
302 - *arg++ = get_canon_hostname();
303 - *arg++ = get_ip_address();
304 - *arg++ = tcp_port.buf;
304 + *arg++ = hi->hostname.buf;
305 + *arg++ = get_canon_hostname(hi);
306 + *arg++ = get_ip_address(hi);
307 + *arg++ = hi->tcp_port.buf;
308 *arg = NULL;
309
310 child.use_shell = 1;
@@ -346,7 +349,8 @@ error_return:
349 return -1;
350 }
351
349 -static int run_service(const char *dir, struct daemon_service *service)
352 +static int run_service(const char *dir, struct daemon_service *service,
353 + struct hostinfo *hi)
354 {
355 const char *path;
356 int enabled = service->enabled;
@@ -360,7 +364,7 @@ static int run_service(const char *dir, struct daemon_service *service)
364 return daemon_error(dir, "service not enabled");
365 }
366
363 - if (!(path = path_ok(dir)))
367 + if (!(path = path_ok(dir, hi)))
368 return daemon_error(dir, "no such repository");
369
370 /*
@@ -396,7 +400,7 @@ static int run_service(const char *dir, struct daemon_service *service)
400 * Optionally, a hook can choose to deny access to the
401 * repository depending on the phase of the moon.
402 */
399 - if (access_hook && run_access_hook(service, dir, path))
403 + if (access_hook && run_access_hook(service, dir, path, hi))
404 return -1;
405
406 /*
@@ -561,14 +565,14 @@ static void canonicalize_client(struct strbuf *out, const char *in)
565 /*
566 * Read the host as supplied by the client connection.
567 */
564 -static void parse_host_arg(char *extra_args, int buflen)
568 +static void parse_host_arg(struct hostinfo *hi, char *extra_args, int buflen)
569 {
570 char *val;
571 int vallen;
572 char *end = extra_args + buflen;
573
574 if (extra_args < end && *extra_args) {
571 - saw_extended_args = 1;
575 + hi->saw_extended_args = 1;
576 if (strncasecmp("host=", extra_args, 5) == 0) {
577 val = extra_args + 5;
578 vallen = strlen(val) + 1;
@@ -577,13 +581,10 @@ static void parse_host_arg(char *extra_args, int buflen)
581 char *host;
582 char *port;
583 parse_host_and_port(val, &host, &port);
580 - if (port) {
581 - strbuf_reset(&tcp_port);
582 - sanitize_client(&tcp_port, port);
583 - }
584 - strbuf_reset(&hostname);
585 - canonicalize_client(&hostname, host);
586 - hostname_lookup_done = 0;
584 + if (port)
585 + sanitize_client(&hi->tcp_port, port);
586 + canonicalize_client(&hi->hostname, host);
587 + hi->hostname_lookup_done = 0;
588 }
589
590 /* On to the next one */
@@ -597,9 +598,9 @@ static void parse_host_arg(char *extra_args, int buflen)
598 /*
599 * Locate canonical hostname and its IP address.
600 */
600 -static void lookup_hostname(void)
601 +static void lookup_hostname(struct hostinfo *hi)
602 {
602 - if (!hostname_lookup_done && hostname.len) {
603 + if (!hi->hostname_lookup_done && hi->hostname.len) {
604 #ifndef NO_IPV6
605 struct addrinfo hints;
606 struct addrinfo *ai;
@@ -609,21 +610,20 @@ static void lookup_hostname(void)
610 memset(&hints, 0, sizeof(hints));
611 hints.ai_flags = AI_CANONNAME;
612
612 - gai = getaddrinfo(hostname.buf, NULL, &hints, &ai);
613 + gai = getaddrinfo(hi->hostname.buf, NULL, &hints, &ai);
614 if (!gai) {
615 struct sockaddr_in *sin_addr = (void *)ai->ai_addr;
616
617 inet_ntop(AF_INET, &sin_addr->sin_addr,
618 addrbuf, sizeof(addrbuf));
618 - strbuf_reset(&ip_address);
619 - strbuf_addstr(&ip_address, addrbuf);
619 + strbuf_addstr(&hi->ip_address, addrbuf);
620
621 - strbuf_reset(&canon_hostname);
621 if (ai->ai_canonname)
623 - sanitize_client(&canon_hostname,
622 + sanitize_client(&hi->canon_hostname,
623 ai->ai_canonname);
624 else
626 - strbuf_addbuf(&canon_hostname, &ip_address);
625 + strbuf_addbuf(&hi->canon_hostname,
626 + &hi->ip_address);
627
628 freeaddrinfo(ai);
629 }
@@ -644,22 +644,39 @@ static void lookup_hostname(void)
644 inet_ntop(hent->h_addrtype, &sa.sin_addr,
645 addrbuf, sizeof(addrbuf));
646
647 - strbuf_reset(&canon_hostname);
648 - sanitize_client(&canon_hostname, hent->h_name);
649 - strbuf_reset(&ip_address);
650 - strbuf_addstr(&ip_address, addrbuf);
647 + sanitize_client(&hi->canon_hostname, hent->h_name);
648 + strbuf_addstr(&hi->ip_address, addrbuf);
649 }
650 #endif
653 - hostname_lookup_done = 1;
651 + hi->hostname_lookup_done = 1;
652 }
653 }
654
655 +static void hostinfo_init(struct hostinfo *hi)
656 +{
657 + memset(hi, 0, sizeof(*hi));
658 + strbuf_init(&hi->hostname, 0);
659 + strbuf_init(&hi->canon_hostname, 0);
660 + strbuf_init(&hi->ip_address, 0);
661 + strbuf_init(&hi->tcp_port, 0);
662 +}
663 +
664 +static void hostinfo_clear(struct hostinfo *hi)
665 +{
666 + strbuf_release(&hi->hostname);
667 + strbuf_release(&hi->canon_hostname);
668 + strbuf_release(&hi->ip_address);
669 + strbuf_release(&hi->tcp_port);
670 +}
671
672 static int execute(void)
673 {
674 char *line = packet_buffer;
675 int pktlen, len, i;
676 char *addr = getenv("REMOTE_ADDR"), *port = getenv("REMOTE_PORT");
677 + struct hostinfo hi;
678 +
679 + hostinfo_init(&hi);
680
681 if (addr)
682 loginfo("Connection from %s:%s", addr, port);
@@ -678,13 +695,8 @@ static int execute(void)
695 pktlen--;
696 }
697
681 - strbuf_release(&hostname);
682 - strbuf_release(&canon_hostname);
683 - strbuf_release(&ip_address);
684 - strbuf_release(&tcp_port);
685 -
698 if (len != pktlen)
687 - parse_host_arg(line + len + 1, pktlen - len - 1);
699 + parse_host_arg(&hi, line + len + 1, pktlen - len - 1);
700
701 for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
702 struct daemon_service *s = &(daemon_service[i]);
@@ -697,10 +709,13 @@ static int execute(void)
709 * Note: The directory here is probably context sensitive,
710 * and might depend on the actual service being performed.
711 */
700 - return run_service(arg, s);
712 + int rc = run_service(arg, s, &hi);
713 + hostinfo_clear(&hi);
714 + return rc;
715 }
716 }
717
718 + hostinfo_clear(&hi);
719 logerror("Protocol error: '%s'", line);
720 return -1;
721 }