Wed, 12 Oct 2022 23:34:20 +0200
add initial ipv6 support
--- a/src/server/daemon/httplistener.c Sun Sep 25 15:40:27 2022 +0200 +++ b/src/server/daemon/httplistener.c Wed Oct 12 23:34:20 2022 +0200 @@ -36,6 +36,7 @@ #include <sys/ipc.h> #include <sys/socket.h> #include <sys/file.h> +#include <arpa/inet.h> #include <netinet/in.h> #include <netdb.h> #include <stdio.h> @@ -46,6 +47,13 @@ #include <stdbool.h> #include <pthread.h> +#include <arpa/inet.h> +#include <netinet/in.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/socket.h> +#include <unistd.h> + #include <ucx/map.h> #include "../util/atomic.h" @@ -91,6 +99,7 @@ newls->default_vs.vs_name = conf->vs.ptr; newls->port = fl->port; newls->server_socket = fl->server_socket; + newls->server_socket6 = fl->server_socket6; newls->running = 1; newls->threadpool = NULL; newls->ref = 2; // 1 reference is fl->next @@ -111,6 +120,12 @@ newls->acceptors[i] = acceptor_new(newls); } + newls->acceptors6 = calloc(newls->nacceptors, sizeof(void*)); + for (int i=0;i<newls->nacceptors;i++) { + newls->acceptors6[i] = acceptor_new(newls); + newls->acceptors6[i]->ipv6 = TRUE; + } + // fl hold one reference of newls fl->next = newls; @@ -118,7 +133,8 @@ ucx_map_sstr_put(listener_map, newls->name, newls); for (int i=0;i<newls->nacceptors;i++) { - acceptor_start(newls->acceptors[i]); + //acceptor_start(newls->acceptors[i]); + acceptor_start(newls->acceptors6[i]); } // check if a restart is required to apply all changes @@ -271,18 +287,29 @@ ucx_map_sstr_put(listener_map, listener->name, listener); struct sockaddr_in servaddr; /* server address */ + struct sockaddr_in6 servaddr6; /* init address structure */ memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(conf->port); + + memset(&servaddr6, 0, sizeof(servaddr6)); + servaddr6.sin6_family = AF_INET6; + servaddr6.sin6_addr = in6addr_any; + servaddr6.sin6_port = htons(conf->port); /* create socket */ if((listener->server_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("Error: http_listener_new: socket"); return NULL; } + + if((listener->server_socket6 = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP)) == -1) { + perror("Error: http_listener_new: socket v6"); + return NULL; + } int o = 1; setsockopt( @@ -290,17 +317,31 @@ SOL_SOCKET, SO_REUSEADDR, &o, sizeof(int)); + o = 1; + setsockopt( + listener->server_socket6, + SOL_SOCKET, SO_REUSEADDR, + &o, + sizeof(int)); /* bind server socket to address */ if(bind(listener->server_socket, (struct sockaddr*)&servaddr, sizeof(servaddr))){ log_ereport(LOG_FAILURE, "http_listener_new: bind failed. Port: %d", conf->port); return NULL; } + + if(bind(listener->server_socket6, (struct sockaddr*)&servaddr6, sizeof(servaddr6))){ + log_ereport(LOG_FAILURE, "http_listener_new: bind v6 failed. Port: %d: %s", conf->port, strerror(errno)); + return NULL; + } /* create acceptors */ listener->acceptors = calloc(listener->nacceptors, sizeof(void*)); + listener->acceptors6 = calloc(listener->nacceptors, sizeof(void*)); for (int i=0;i<listener->nacceptors;i++) { listener->acceptors[i] = acceptor_new(listener); + listener->acceptors6[i] = acceptor_new(listener); + listener->acceptors6[i]->ipv6 = TRUE; } return listener; @@ -316,10 +357,15 @@ log_ereport(LOG_FAILURE, "http_listener_start: listen failed"); return -1; } + if (listen(listener->server_socket6, 256) == -1) { + log_ereport(LOG_FAILURE, "http_listener_start: listen failed"); + return -1; + } /* start acceptor threads */ for (int i=0;i<listener->nacceptors;i++) { acceptor_start(listener->acceptors[i]); + acceptor_start(listener->acceptors6[i]); } return 0; @@ -344,6 +390,7 @@ Acceptor* acceptor_new(HttpListener *listener) { Acceptor *acceptor = malloc(sizeof(Acceptor)); acceptor->listener = listener; + acceptor->ipv6 = WS_FALSE; return acceptor; } @@ -366,19 +413,37 @@ HttpListener *listener = acceptor->listener; + int server_socket; + + ConnectionAddr ca; + struct sockaddr *ca_ptr; + socklen_t ca_length; + ConnectionAddrType addr_type; + if(acceptor->ipv6) { + server_socket = listener->server_socket6; + ca_ptr = (struct sockaddr*)&ca.address_v6; + ca_length = sizeof(ca.address_v6); + addr_type = CONN_ADDR_IPV6; + } else { + server_socket = listener->server_socket; + ca_ptr = (struct sockaddr*)&ca.address_v4; + ca_length = sizeof(ca.address_v4); + addr_type = CONN_ADDR_IPV4; + } + + for (;;) { /* accept connections */ - struct sockaddr_in ca; - socklen_t length = sizeof(ca); int clientfd; + socklen_t length = ca_length; /* accept a connection */ clientfd = accept( - listener->server_socket, - (struct sockaddr*)&ca, + server_socket, + ca_ptr, &length); if (clientfd == -1) { - perror("Error: acceptor_thread: accept"); + log_ereport(LOG_FAILURE, "accept %s failed: %s", acceptor->ipv6 ? "ipv6" : "ipv4", strerror(errno)); continue; } @@ -393,6 +458,7 @@ /* create Connection object */ Connection *conn = malloc(sizeof(Connection)); conn->address = ca; + conn->addr_type = addr_type; conn->fd = clientfd; conn->listener = ls; conn->ssl_accepted = 0;
--- a/src/server/daemon/httplistener.h Sun Sep 25 15:40:27 2022 +0200 +++ b/src/server/daemon/httplistener.h Wed Oct 12 23:34:20 2022 +0200 @@ -73,6 +73,7 @@ struct _acceptor { pthread_t tid; HttpListener *listener; + WSBool ipv6; }; struct _http_listener { @@ -81,10 +82,12 @@ union vs default_vs; int port; int server_socket; + int server_socket6; SessionHandler *session_handler; threadpool_t *threadpool; HttpListener *next; Acceptor **acceptors; + Acceptor **acceptors6; int nacceptors; int running; HttpSSL *ssl;
--- a/src/server/daemon/httprequest.c Sun Sep 25 15:40:27 2022 +0200 +++ b/src/server/daemon/httprequest.c Wed Oct 12 23:34:20 2022 +0200 @@ -165,13 +165,16 @@ // add ip to sn->client pblock char ip_str[INET_ADDRSTRLEN]; - if(inet_ntop( - AF_INET, - &request->connection->address.sin_addr, - ip_str, - INET_ADDRSTRLEN) != NULL) - { - pblock_kvinsert(pb_key_ip, ip_str, INET_ADDRSTRLEN, sn->sn.client); + // TODO: ipv6 + if(request->connection->addr_type == CONN_ADDR_IPV4) { + if(inet_ntop( + AF_INET, + &request->connection->address.address_v4.sin_addr, + ip_str, + INET_ADDRSTRLEN) != NULL) + { + pblock_kvinsert(pb_key_ip, ip_str, INET_ADDRSTRLEN, sn->sn.client); + } } // init NSAPI request structure
--- a/src/server/daemon/sessionhandler.h Sun Sep 25 15:40:27 2022 +0200 +++ b/src/server/daemon/sessionhandler.h Wed Oct 12 23:34:20 2022 +0200 @@ -45,9 +45,24 @@ typedef struct _session_handler SessionHandler; typedef struct _connection Connection; +typedef union ConnectionAddr ConnectionAddr; + +union ConnectionAddr { + struct sockaddr_in address_v4; + struct sockaddr_in6 address_v6; +}; + +enum ConnectionAddrType { + CONN_ADDR_IPV4 = 0, + CONN_ADDR_IPV6 +}; + +typedef enum ConnectionAddrType ConnectionAddrType; + struct _connection { int fd; - struct sockaddr_in address; + ConnectionAddr address; + ConnectionAddrType addr_type; HttpListener *listener; SessionHandler *session_handler; SSL *ssl;
--- a/src/server/webdav/webdav.c Sun Sep 25 15:40:27 2022 +0200 +++ b/src/server/webdav/webdav.c Wed Oct 12 23:34:20 2022 +0200 @@ -539,21 +539,20 @@ protocol_status(sn, rq, 201, NULL); protocol_start_response(sn, rq); ret = REQ_PROCEED; - } else { - if(rq->status_num <= 0) { - int status_code = 500; - if(op->vfs->vfs_errno == EEXIST) { - // 405 (Method Not Allowed) - MKCOL can only be executed on an unmapped URL. - status_code = 405; - } else if(op->vfs->vfs_errno == ENOENT) { - // 409 (Conflict) - A collection cannot be made at the Request-URI until - // one or more intermediate collections have been created. The server - // MUST NOT create those intermediate collections automatically. - status_code = 409; - } - protocol_status(sn, rq, status_code, NULL); + } else if(rq->status_num <= 0) { + int status_code = 500; + if(op->vfs->vfs_errno == EEXIST) { + // 405 (Method Not Allowed) - MKCOL can only be executed on an unmapped URL. + status_code = 405; + } else if(op->vfs->vfs_errno == ENOENT) { + // 409 (Conflict) - A collection cannot be made at the Request-URI until + // one or more intermediate collections have been created. The server + // MUST NOT create those intermediate collections automatically. + status_code = 409; + } else { + log_ereport(LOG_VERBOSE, "webdav_mkcol: errno: %d", op->vfs->vfs_errno); } - + protocol_status(sn, rq, status_code, NULL); } return ret;