mirror of
https://github.com/emikulic/darkhttpd.git
synced 2023-08-10 21:13:08 +03:00
Add support for IPv6.
This commit is contained in:
parent
02b02a7615
commit
72159c5010
127
darkhttpd.c
127
darkhttpd.c
@ -204,7 +204,11 @@ struct connection {
|
|||||||
LIST_ENTRY(connection) entries;
|
LIST_ENTRY(connection) entries;
|
||||||
|
|
||||||
int socket;
|
int socket;
|
||||||
|
#ifdef HAVE_INET6
|
||||||
|
struct in6_addr client;
|
||||||
|
#else
|
||||||
in_addr_t client;
|
in_addr_t client;
|
||||||
|
#endif
|
||||||
time_t last_active;
|
time_t last_active;
|
||||||
enum {
|
enum {
|
||||||
RECV_REQUEST, /* receiving request */
|
RECV_REQUEST, /* receiving request */
|
||||||
@ -268,13 +272,14 @@ static time_t now;
|
|||||||
#define MAX_REQUEST_LENGTH 4000
|
#define MAX_REQUEST_LENGTH 4000
|
||||||
|
|
||||||
/* Defaults can be overridden on the command-line */
|
/* Defaults can be overridden on the command-line */
|
||||||
static in_addr_t bindaddr = INADDR_ANY;
|
static const char *bindaddr;
|
||||||
static uint16_t bindport = 8080; /* or 80 if running as root */
|
static uint16_t bindport = 8080; /* or 80 if running as root */
|
||||||
static int max_connections = -1; /* kern.ipc.somaxconn */
|
static int max_connections = -1; /* kern.ipc.somaxconn */
|
||||||
static const char *index_name = "index.html";
|
static const char *index_name = "index.html";
|
||||||
static int no_listing = 0;
|
static int no_listing = 0;
|
||||||
|
|
||||||
static int sockin = -1; /* socket to accept connections from */
|
static int sockin = -1; /* socket to accept connections from */
|
||||||
|
static int inet6 = 0; /* whether the socket uses inet6 */
|
||||||
static char *wwwroot = NULL; /* a path name */
|
static char *wwwroot = NULL; /* a path name */
|
||||||
static char *logfile_name = NULL; /* NULL = no logging */
|
static char *logfile_name = NULL; /* NULL = no logging */
|
||||||
static FILE *logfile = NULL;
|
static FILE *logfile = NULL;
|
||||||
@ -796,16 +801,47 @@ static const char *url_content_type(const char *url) {
|
|||||||
return default_mimetype;
|
return default_mimetype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *get_address_text(const void *addr) {
|
||||||
|
if (inet6) {
|
||||||
|
#ifdef HAVE_INET6
|
||||||
|
static char text_addr[INET6_ADDRSTRLEN];
|
||||||
|
inet_ntop(AF_INET6, (struct in6_addr *)addr, text_addr,
|
||||||
|
INET6_ADDRSTRLEN);
|
||||||
|
return text_addr;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
return inet_ntoa(*(struct in_addr *)addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize the sockin global. This is the socket that we accept
|
/* Initialize the sockin global. This is the socket that we accept
|
||||||
* connections from.
|
* connections from.
|
||||||
*/
|
*/
|
||||||
static void init_sockin(void) {
|
static void init_sockin(void) {
|
||||||
struct sockaddr_in addrin;
|
struct sockaddr_in addrin;
|
||||||
|
#ifdef HAVE_INET6
|
||||||
|
struct sockaddr_in6 addrin6;
|
||||||
|
#endif
|
||||||
socklen_t addrin_len;
|
socklen_t addrin_len;
|
||||||
int sockopt;
|
int sockopt;
|
||||||
|
|
||||||
/* create incoming socket */
|
if (inet6) {
|
||||||
sockin = socket(PF_INET, SOCK_STREAM, 0);
|
#ifdef HAVE_INET6
|
||||||
|
memset(&addrin6, 0, sizeof(addrin6));
|
||||||
|
if (inet_pton(AF_INET6, bindaddr ? bindaddr : "::",
|
||||||
|
&addrin6.sin6_addr) == -1) {
|
||||||
|
errx(1, "malformed --addr argument");
|
||||||
|
}
|
||||||
|
sockin = socket(PF_INET6, SOCK_STREAM, 0);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
memset(&addrin, 0, sizeof(addrin));
|
||||||
|
addrin.sin_addr.s_addr = bindaddr ? inet_addr(bindaddr) : INADDR_ANY;
|
||||||
|
if (addrin.sin_addr.s_addr == (in_addr_t)INADDR_NONE)
|
||||||
|
errx(1, "malformed --addr argument");
|
||||||
|
sockin = socket(PF_INET, SOCK_STREAM, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (sockin == -1)
|
if (sockin == -1)
|
||||||
err(1, "socket()");
|
err(1, "socket()");
|
||||||
|
|
||||||
@ -834,20 +870,38 @@ static void init_sockin(void) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* bind socket */
|
/* bind socket */
|
||||||
addrin.sin_family = (u_char)PF_INET;
|
if (inet6) {
|
||||||
addrin.sin_port = htons(bindport);
|
#ifdef HAVE_INET6
|
||||||
addrin.sin_addr.s_addr = bindaddr;
|
addrin6.sin6_family = AF_INET6;
|
||||||
memset(&(addrin.sin_zero), 0, 8);
|
addrin6.sin6_port = htons(bindport);
|
||||||
if (bind(sockin, (struct sockaddr *)&addrin,
|
if (bind(sockin, (struct sockaddr *)&addrin6,
|
||||||
sizeof(struct sockaddr)) == -1)
|
sizeof(struct sockaddr_in6)) == -1)
|
||||||
err(1, "bind(port %u)", bindport);
|
err(1, "bind(port %u)", bindport);
|
||||||
|
|
||||||
|
addrin_len = sizeof(addrin6);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
addrin.sin_family = (u_char)PF_INET;
|
||||||
|
addrin.sin_port = htons(bindport);
|
||||||
|
if (bind(sockin, (struct sockaddr *)&addrin,
|
||||||
|
sizeof(struct sockaddr_in)) == -1)
|
||||||
|
err(1, "bind(port %u)", bindport);
|
||||||
|
|
||||||
|
addrin_len = sizeof(addrin);
|
||||||
|
}
|
||||||
|
|
||||||
addrin_len = sizeof(addrin);
|
|
||||||
if (getsockname(sockin, (struct sockaddr *)&addrin, &addrin_len) == -1)
|
if (getsockname(sockin, (struct sockaddr *)&addrin, &addrin_len) == -1)
|
||||||
err(1, "getsockname()");
|
err(1, "getsockname()");
|
||||||
|
|
||||||
printf("listening on: http://%s:%u/\n",
|
if (inet6) {
|
||||||
inet_ntoa(addrin.sin_addr), ntohs(addrin.sin_port));
|
#ifdef HAVE_INET6
|
||||||
|
printf("listening on: http://[%s]:%u/\n",
|
||||||
|
get_address_text(&addrin6.sin6_addr), bindport);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
printf("listening on: http://%s:%u/\n",
|
||||||
|
get_address_text(&addrin.sin_addr), bindport);
|
||||||
|
}
|
||||||
|
|
||||||
/* listen on socket */
|
/* listen on socket */
|
||||||
if (listen(sockin, max_connections) == -1)
|
if (listen(sockin, max_connections) == -1)
|
||||||
@ -918,6 +972,10 @@ static void usage(const char *argv0) {
|
|||||||
printf("\t--no-server-id\n"
|
printf("\t--no-server-id\n"
|
||||||
"\t\tDon't identify the server type in headers\n"
|
"\t\tDon't identify the server type in headers\n"
|
||||||
"\t\tor directory listings.\n");
|
"\t\tor directory listings.\n");
|
||||||
|
#ifdef HAVE_INET6
|
||||||
|
printf("\t--ipv6\n"
|
||||||
|
"\t\tListen on IPv6 address.\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns 1 if string is a number, 0 otherwise. Set num to NULL if
|
/* Returns 1 if string is a number, 0 otherwise. Set num to NULL if
|
||||||
@ -979,9 +1037,7 @@ static void parse_commandline(const int argc, char *argv[]) {
|
|||||||
else if (strcmp(argv[i], "--addr") == 0) {
|
else if (strcmp(argv[i], "--addr") == 0) {
|
||||||
if (++i >= argc)
|
if (++i >= argc)
|
||||||
errx(1, "missing ip after --addr");
|
errx(1, "missing ip after --addr");
|
||||||
bindaddr = inet_addr(argv[i]);
|
bindaddr = argv[i];
|
||||||
if (bindaddr == (in_addr_t)INADDR_NONE)
|
|
||||||
errx(1, "malformed --addr argument");
|
|
||||||
}
|
}
|
||||||
else if (strcmp(argv[i], "--maxconn") == 0) {
|
else if (strcmp(argv[i], "--maxconn") == 0) {
|
||||||
if (++i >= argc)
|
if (++i >= argc)
|
||||||
@ -1071,6 +1127,11 @@ static void parse_commandline(const int argc, char *argv[]) {
|
|||||||
else if (strcmp(argv[i], "--no-server-id") == 0) {
|
else if (strcmp(argv[i], "--no-server-id") == 0) {
|
||||||
want_server_id = 0;
|
want_server_id = 0;
|
||||||
}
|
}
|
||||||
|
#ifdef HAVE_INET6
|
||||||
|
else if (strcmp(argv[i], "--ipv6") == 0) {
|
||||||
|
inet6 = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
else
|
else
|
||||||
errx(1, "unknown argument `%s'", argv[i]);
|
errx(1, "unknown argument `%s'", argv[i]);
|
||||||
}
|
}
|
||||||
@ -1081,7 +1142,7 @@ static struct connection *new_connection(void) {
|
|||||||
struct connection *conn = xmalloc(sizeof(struct connection));
|
struct connection *conn = xmalloc(sizeof(struct connection));
|
||||||
|
|
||||||
conn->socket = -1;
|
conn->socket = -1;
|
||||||
conn->client = INADDR_ANY;
|
memset(&conn->client, 0, sizeof(conn->client));
|
||||||
conn->last_active = now;
|
conn->last_active = now;
|
||||||
conn->request = NULL;
|
conn->request = NULL;
|
||||||
conn->request_length = 0;
|
conn->request_length = 0;
|
||||||
@ -1119,22 +1180,41 @@ static struct connection *new_connection(void) {
|
|||||||
/* Accept a connection from sockin and add it to the connection queue. */
|
/* Accept a connection from sockin and add it to the connection queue. */
|
||||||
static void accept_connection(void) {
|
static void accept_connection(void) {
|
||||||
struct sockaddr_in addrin;
|
struct sockaddr_in addrin;
|
||||||
|
#ifdef HAVE_INET6
|
||||||
|
struct sockaddr_in6 addrin6;
|
||||||
|
#endif
|
||||||
socklen_t sin_size;
|
socklen_t sin_size;
|
||||||
struct connection *conn;
|
struct connection *conn;
|
||||||
|
|
||||||
/* allocate and initialise struct connection */
|
/* allocate and initialise struct connection */
|
||||||
conn = new_connection();
|
conn = new_connection();
|
||||||
|
|
||||||
sin_size = sizeof(addrin);
|
if (inet6) {
|
||||||
memset(&addrin, 0, sin_size);
|
#ifdef HAVE_INET6
|
||||||
conn->socket = accept(sockin, (struct sockaddr *)&addrin, &sin_size);
|
sin_size = sizeof(addrin6);
|
||||||
|
memset(&addrin6, 0, sin_size);
|
||||||
|
conn->socket = accept(sockin, (struct sockaddr *)&addrin6, &sin_size);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
sin_size = sizeof(addrin);
|
||||||
|
memset(&addrin, 0, sin_size);
|
||||||
|
conn->socket = accept(sockin, (struct sockaddr *)&addrin, &sin_size);
|
||||||
|
}
|
||||||
|
|
||||||
if (conn->socket == -1)
|
if (conn->socket == -1)
|
||||||
err(1, "accept()");
|
err(1, "accept()");
|
||||||
|
|
||||||
nonblock_socket(conn->socket);
|
nonblock_socket(conn->socket);
|
||||||
|
|
||||||
conn->state = RECV_REQUEST;
|
conn->state = RECV_REQUEST;
|
||||||
conn->client = addrin.sin_addr.s_addr;
|
|
||||||
|
if (inet6) {
|
||||||
|
#ifdef HAVE_INET6
|
||||||
|
conn->client = addrin6.sin6_addr;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
*(in_addr_t *)&conn->client = addrin.sin_addr.s_addr;
|
||||||
|
}
|
||||||
LIST_INSERT_HEAD(&connlist, conn, entries);
|
LIST_INSERT_HEAD(&connlist, conn, entries);
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
@ -1173,7 +1253,6 @@ static void logencode(const char *src, char *dest) {
|
|||||||
|
|
||||||
/* Add a connection's details to the logfile. */
|
/* Add a connection's details to the logfile. */
|
||||||
static void log_connection(const struct connection *conn) {
|
static void log_connection(const struct connection *conn) {
|
||||||
struct in_addr inaddr;
|
|
||||||
char *safe_method, *safe_url, *safe_referer, *safe_user_agent;
|
char *safe_method, *safe_url, *safe_referer, *safe_user_agent;
|
||||||
|
|
||||||
if (logfile == NULL)
|
if (logfile == NULL)
|
||||||
@ -1183,8 +1262,6 @@ static void log_connection(const struct connection *conn) {
|
|||||||
if (conn->method == NULL)
|
if (conn->method == NULL)
|
||||||
return; /* invalid - didn't parse - maybe too long */
|
return; /* invalid - didn't parse - maybe too long */
|
||||||
|
|
||||||
inaddr.s_addr = conn->client;
|
|
||||||
|
|
||||||
#define make_safe(x) \
|
#define make_safe(x) \
|
||||||
if (conn->x) { \
|
if (conn->x) { \
|
||||||
safe_##x = xmalloc(strlen(conn->x)*3 + 1); \
|
safe_##x = xmalloc(strlen(conn->x)*3 + 1); \
|
||||||
@ -1202,7 +1279,7 @@ static void log_connection(const struct connection *conn) {
|
|||||||
|
|
||||||
fprintf(logfile, "%lu %s \"%s %s\" %d %llu \"%s\" \"%s\"\n",
|
fprintf(logfile, "%lu %s \"%s %s\" %d %llu \"%s\" \"%s\"\n",
|
||||||
(unsigned long int)now,
|
(unsigned long int)now,
|
||||||
inet_ntoa(inaddr),
|
get_address_text(&conn->client),
|
||||||
use_safe(method),
|
use_safe(method),
|
||||||
use_safe(url),
|
use_safe(url),
|
||||||
conn->http_code,
|
conn->http_code,
|
||||||
|
Loading…
Reference in New Issue
Block a user