#include "fd.h"
#include "chunk_queue.h"
+/** Message sent to clients that do not send a valid get request. */
#define HTTP_ERR_MSG "HTTP/1.0 400 Bad Request\n"
-/** \endcond */
+
/** The possible states of a client from the server's POV. */
enum http_status {
static void http_shutdown_client(struct http_client *hc, const char *msg)
{
- PARA_INFO_LOG("shutting down %s on fd %d (%s)\n",
- hc->name, hc->fd, msg);
+ PARA_INFO_LOG("shutting down %s on fd %d (%s)\n", hc->name, hc->fd,
+ msg);
numclients--;
free(hc->name);
close(hc->fd);
}
}
+/**
+ * Return true if addr_1 matches addr_2 in the first `netmask' bits.
+ */
+static int v4_addr_match(uint32_t addr_1, uint32_t addr_2, uint8_t netmask)
+{
+ uint32_t mask = ~0U;
+
+ if (netmask < 32)
+ mask <<= (32 - netmask);
+ return (htonl(addr_1) & mask) == (htonl(addr_2) & mask);
+}
+
static int host_in_access_perm_list(struct http_client *hc)
{
- struct sockaddr_storage ss;
- socklen_t sslen = sizeof(ss);
+ struct access_info *ai, *tmp;
+ struct sockaddr_storage ss;
+ socklen_t sslen = sizeof(ss);
+ struct in_addr v4_addr;
if (getpeername(hc->fd, (struct sockaddr *)&ss, &sslen) < 0) {
- PARA_ERROR_LOG("can not determine address family: %s\n", strerror(errno));
- } else if (ss.ss_family == AF_INET) {
- /* FIXME: access restriction is (currently) only supported for IPv4 */
- struct access_info *ai, *tmp;
- struct in_addr client_addr = ((struct sockaddr_in *)&ss)->sin_addr;
-
- list_for_each_entry_safe(ai, tmp, &access_perm_list, node) {
- unsigned mask = ((~0U) >> ai->netmask);
- if ((client_addr.s_addr & mask) == (ai->addr.s_addr & mask))
- return 1;
- }
+ PARA_ERROR_LOG("Can not determine peer address: %s\n", strerror(errno));
+ goto no_match;
}
+ v4_addr = extract_v4_addr(&ss);
+ if (!v4_addr.s_addr)
+ goto no_match;
+
+ list_for_each_entry_safe(ai, tmp, &access_perm_list, node)
+ if (v4_addr_match(v4_addr.s_addr, ai->addr.s_addr, ai->netmask))
+ return 1;
+no_match:
return 0;
}
hc->cq = cq_new(MAX_BACKLOG);
numclients++;
PARA_INFO_LOG("accepted client #%d: %s (fd %d)\n", numclients,
- hc->name, hc->fd);
+ hc->name, hc->fd);
para_list_add(&hc->node, &clients);
add_close_on_fork_list(hc->fd);
mark_fd_nonblocking(hc->fd);
return;
err_out:
PARA_WARNING_LOG("ignoring connect request from %s (%s)\n",
- hc->name, err_msg);
+ hc->name, err_msg);
if (hc->fd > 0)
close(hc->fd);
free(hc);
ap = tmp;
}
list_for_each_entry_safe(hc, tmp_hc, &clients, node) {
- char *tmp = make_message("%s%s ", clnts? clnts : "",
- hc->name);
+ char *tmp = make_message("%s%s ", clnts? clnts : "", hc->name);
free(clnts);
clnts = tmp;
}