X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=http_send.c;h=28e245eae13ac6b7ce8e0a5f162ab88be52b5a60;hp=8cce85a15c079599f16ea5e800082cbe0db2b215;hb=eb578d92fd87aeb86c0832689000dc772e689f92;hpb=24e2b57dde50a6fe33deee034d34181eece09834 diff --git a/http_send.c b/http_send.c index 8cce85a1..28e245ea 100644 --- a/http_send.c +++ b/http_send.c @@ -25,8 +25,9 @@ #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 { @@ -201,24 +202,37 @@ static void http_send( long unsigned current_chunk, } } +/** + * 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; }