X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=http_send.c;h=28e245eae13ac6b7ce8e0a5f162ab88be52b5a60;hp=799c06cc2dfa2b4400882cdb14fb16089d1bc77e;hb=23c74bcff23e2eca0b37dbdb2def8fc132fe36f3;hpb=7a0852896a75d852dbd2ac848ec5c0be3b5dea71 diff --git a/http_send.c b/http_send.c index 799c06cc..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 { @@ -87,8 +88,8 @@ static struct sender *self; 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); @@ -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; } @@ -291,14 +305,14 @@ static void http_post_select(fd_set *rfds, fd_set *wfds) 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); @@ -435,8 +449,7 @@ static char *http_info(void) 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; }