#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 {
}
}
+/**
+ * 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;
}