Feature #1908 ยป lighttpd-1.4.21-random-port.patch
lighttpd-1.4.21/doc/lighttpd.conf 2009-02-19 12:51:59.000000000 +0100 | ||
---|---|---|
## bind to port (default: 80)
|
||
#server.port = 81
|
||
## if server.port = 0 the bound port is written to
|
||
#server.port-file = "/var/run/lighttpd.port"
|
||
## bind to localhost (default: all interfaces)
|
||
#server.bind = "127.0.0.1"
|
||
lighttpd-1.4.21/src/array.h 2009-02-19 12:53:31.000000000 +0100 | ||
---|---|---|
buffer *host;
|
||
unsigned short port;
|
||
/* we use port == -1 to determine an uninitialized port */
|
||
int port;
|
||
time_t disable_ts;
|
||
int is_disabled;
|
lighttpd-1.4.21/src/base.h 2009-02-19 13:12:45.000000000 +0100 | ||
---|---|---|
typedef enum { T_CONFIG_UNSET,
|
||
T_CONFIG_STRING,
|
||
T_CONFIG_SHORT,
|
||
T_CONFIG_INT,
|
||
T_CONFIG_BOOLEAN,
|
||
T_CONFIG_ARRAY,
|
||
T_CONFIG_LOCAL,
|
||
... | ... | |
} buffer_plugin;
|
||
typedef struct {
|
||
unsigned short port;
|
||
int port;
|
||
buffer *bindhost;
|
||
buffer *errorlog_file;
|
||
... | ... | |
} stat_cache_engine;
|
||
unsigned short enable_cores;
|
||
unsigned short reject_expect_100_with_417;
|
||
buffer *port_file; /* stores the assigned port for port == 0 */
|
||
} server_config;
|
||
typedef struct {
|
||
... | ... | |
uid_t uid;
|
||
gid_t gid;
|
||
int port_file_fd; /* fd to write the port-number to if server.port == 0 */
|
||
} server;
|
||
lighttpd-1.4.21/src/configfile.c 2009-02-19 13:21:31.000000000 +0100 | ||
---|---|---|
{ "server.chroot", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 3 */
|
||
{ "server.username", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 4 */
|
||
{ "server.groupname", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 5 */
|
||
{ "server.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 6 */
|
||
/* type is INT to allow value 0 for random server port and -1 for default */
|
||
{ "server.port", NULL, T_CONFIG_INT, T_CONFIG_SCOPE_SERVER }, /* 6 */
|
||
{ "server.tag", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
|
||
{ "server.use-ipv6", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
|
||
{ "server.modules", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_SERVER }, /* 9 */
|
||
... | ... | |
{ "etag.use-size", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 51 */
|
||
{ "server.reject-expect-100-with-417", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 52 */
|
||
{ "debug.log-timeouts", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 53 */
|
||
{ "server.port-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 54 */
|
||
{ "server.host", "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
|
||
{ "server.docroot", "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
|
||
{ "server.virtual-root", "load mod_simple_vhost and use simple-vhost.server-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
|
||
... | ... | |
cv[50].destination = &(s->etag_use_mtime);
|
||
cv[51].destination = &(s->etag_use_size);
|
||
cv[54].destination = srv->srvconf.port_file;
|
||
srv->config_storage[i] = s;
|
||
if (0 != (ret = config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv))) {
|
||
... | ... | |
}
|
||
}
|
||
if (srv->srvconf.port == 0) {
|
||
/* port == -1: means port is still unset (no configuration-value was set in configfile) -> use default */
|
||
if (srv->srvconf.port == -1) {
|
||
srv->srvconf.port = s->is_ssl ? 443 : 80;
|
||
}
|
||
lighttpd-1.4.21/src/configfile-glue.c 2009-02-19 13:56:59.000000000 +0100 | ||
---|---|---|
#include <string.h>
|
||
#include <stdlib.h>
|
||
#include <values.h>
|
||
#include "base.h"
|
||
#include "buffer.h"
|
||
... | ... | |
return -1;
|
||
}
|
||
break;
|
||
case T_CONFIG_INT:
|
||
switch(du->type) {
|
||
case TYPE_INTEGER: {
|
||
data_integer *di = (data_integer *)du;
|
||
*((int *)(cv[i].destination)) = di->value;
|
||
break;
|
||
}
|
||
case TYPE_STRING: {
|
||
data_string *ds = (data_string *)du;
|
||
/* If the value came from an environment variable, then it is a
|
||
* data_string, although it may contain a number in ASCII
|
||
* decimal format. We try to interpret the string as a decimal
|
||
* short before giving up, in order to support setting numeric
|
||
* values with environment variables (eg, port number).
|
||
*/
|
||
if (ds->value->ptr && *ds->value->ptr) {
|
||
char *e;
|
||
long l = strtol(ds->value->ptr, &e, 11);
|
||
if (e != ds->value->ptr && !*e && l >= MININT && l <= MAXINT) {
|
||
*((int *)(cv[i].destination)) = l;
|
||
break;
|
||
}
|
||
}
|
||
log_error_write(srv, __FILE__, __LINE__, "ssb", "got a string but expected an integer:", cv[i].key, ds->value);
|
||
return -1;
|
||
}
|
||
default:
|
||
log_error_write(srv, __FILE__, __LINE__, "ssds", "unexpected type for key:", cv[i].key, du->type, "expected an integer, range ", MININT, " ... ", MAXINT);
|
||
return -1;
|
||
}
|
||
break;
|
||
case T_CONFIG_BOOLEAN:
|
||
if (du->type == TYPE_STRING) {
|
||
data_string *ds = (data_string *)du;
|
lighttpd-1.4.21/src/network.c 2009-02-19 14:11:41.000000000 +0100 | ||
---|---|---|
#include <string.h>
|
||
#include <stdlib.h>
|
||
#include <assert.h>
|
||
#include <stdio.h>
|
||
#include "network.h"
|
||
#include "fdevent.h"
|
||
... | ... | |
buffer *b;
|
||
int is_unix_domain_socket = 0;
|
||
int fd;
|
||
char assigned_port_buf[7]; /* 5 chars for port + 1 for \n + 1 for \0 */
|
||
unsigned short assigned_port = 0;
|
||
#ifdef SO_ACCEPTFILTER
|
||
struct accept_filter_arg afa;
|
||
... | ... | |
}
|
||
#endif
|
||
srv_socket = calloc(1, sizeof(*srv_socket));
|
||
if (NULL == (srv_socket = calloc(1, sizeof(*srv_socket)))) {
|
||
log_error_write(srv, __FILE__, __LINE__, "s", "can't allocate memory for srv_socket");
|
||
return -1;
|
||
}
|
||
srv_socket->fd = -1;
|
||
srv_socket->srv_token = buffer_init();
|
||
... | ... | |
if (host[0] == '/') {
|
||
/* host is a unix-domain-socket */
|
||
is_unix_domain_socket = 1;
|
||
} else if (port == 0 || port > 65535) {
|
||
} else if (port > 65535) {
|
||
/* port == 0 selects a random port which is reported back after binding */
|
||
log_error_write(srv, __FILE__, __LINE__, "sd", "port out of range:", port);
|
||
return -1;
|
||
... | ... | |
return -1;
|
||
}
|
||
errno = 0;
|
||
if (0 != bind(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) {
|
||
switch(srv_socket->addr.plain.sa_family) {
|
||
case AF_UNIX:
|
||
... | ... | |
}
|
||
return -1;
|
||
}
|
||
if ( 0 == port ) {
|
||
switch(srv_socket->addr.plain.sa_family) {
|
||
case AF_UNIX:
|
||
/* nothing to do here */
|
||
break;
|
||
default:
|
||
/* get assigned port */
|
||
#ifdef HAVE_IPV6
|
||
if (s->use_ipv6) {
|
||
errno = 0;
|
||
if ( -1 == getsockname( srv_socket->fd, (struct sockaddr*) &(srv_socket->addr), &addr_len)) {
|
||
log_error_write(srv, __FILE__, __LINE__, "ss",
|
||
"can't get socket info:",
|
||
strerror(errno));
|
||
return -1;
|
||
}
|
||
assigned_port = ntohs(srv_socket->addr.ipv6.sin6_port);
|
||
}
|
||
#endif
|
||
if (0 == assigned_port) {
|
||
errno = 0;
|
||
if ( -1 == getsockname( srv_socket->fd, (struct sockaddr*) &(srv_socket->addr), &addr_len)) {
|
||
log_error_write(srv, __FILE__, __LINE__, "ss",
|
||
"can't get socket info:",
|
||
strerror(errno));
|
||
return -1;
|
||
}
|
||
assigned_port = ntohs(srv_socket->addr.ipv4.sin_port);
|
||
}
|
||
sprintf(assigned_port_buf, "%u\n", assigned_port);
|
||
if ( write(srv->port_file_fd, assigned_port_buf, strlen(assigned_port_buf)) <= 0 ) {
|
||
log_error_write(srv, __FILE__, __LINE__, "sd", "failed to write assigned port to file:", assigned_port );
|
||
}
|
||
close(srv->port_file_fd);
|
||
srv->port_file_fd = -1;
|
||
}
|
||
}
|
||
if (-1 == listen(srv_socket->fd, 128 * 8)) {
|
||
log_error_write(srv, __FILE__, __LINE__, "ss", "listen failed: ", strerror(errno));
|
lighttpd-1.4.21/src/server.c 2009-02-19 14:22:08.000000000 +0100 | ||
---|---|---|
CLEAN(srvconf.bindhost);
|
||
CLEAN(srvconf.event_handler);
|
||
CLEAN(srvconf.pid_file);
|
||
CLEAN(srvconf.port_file);
|
||
CLEAN(tmp_chunk_len);
|
||
#undef CLEAN
|
||
... | ... | |
CLEAN(srvconf.pid_file);
|
||
CLEAN(srvconf.modules_dir);
|
||
CLEAN(srvconf.network_backend);
|
||
CLEAN(srvconf.port_file);
|
||
CLEAN(tmp_chunk_len);
|
||
#undef CLEAN
|
||
... | ... | |
int o;
|
||
int num_childs = 0;
|
||
int pid_fd = -1, fd;
|
||
int port_fd = -1;
|
||
size_t i;
|
||
#ifdef HAVE_SIGACTION
|
||
struct sigaction act;
|
||
... | ... | |
/* init structs done */
|
||
srv->srvconf.port = 0;
|
||
/* port == -1: port is unset -> use default */
|
||
srv->srvconf.port = -1;
|
||
#ifdef HAVE_GETUID
|
||
i_am_root = (getuid() == 0);
|
||
#else
|
||
... | ... | |
}
|
||
}
|
||
/* srv->srvconf.port should be set now if not panic */
|
||
assert(srv->srvconf.port >= 0);
|
||
/* open port file BEFORE chroot but only if server.port == 0 */
|
||
if ((0 == srv->srvconf.port) && srv->srvconf.port_file->used) {
|
||
if (-1 == (port_fd = open(srv->srvconf.port_file->ptr, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
|
||
struct stat st;
|
||
if (errno != EEXIST) {
|
||
log_error_write(srv, __FILE__, __LINE__, "sbs",
|
||
"opening port-file failed:", srv->srvconf.port_file, strerror(errno));
|
||
return -1;
|
||
}
|
||
if (0 != stat(srv->srvconf.port_file->ptr, &st)) {
|
||
log_error_write(srv, __FILE__, __LINE__, "sbs",
|
||
"stating existing port-file failed:",
|
||
srv->srvconf.port_file, strerror(errno));
|
||
}
|
||
if (!S_ISREG(st.st_mode)) {
|
||
log_error_write(srv, __FILE__, __LINE__, "sb",
|
||
"port-file exists and isn't regular file:", srv->srvconf.port_file);
|
||
return -1;
|
||
}
|
||
if (-1 == (port_fd = open(srv->srvconf.port_file->ptr, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
|
||
log_error_write(srv, __FILE__, __LINE__, "sbs",
|
||
"opening port-file failed:", srv->srvconf.port_file, strerror(errno));
|
||
return -1;
|
||
}
|
||
}
|
||
srv->port_file_fd = port_fd;
|
||
}
|
||
if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
|
||
/* select limits itself
|
||
*
|
||
... | ... | |
}
|
||
}
|
||
}
|
||
if (srv->srvconf.port_file->used &&
|
||
srv->srvconf.changeroot->used == 0) {
|
||
if (0 != unlink(srv->srvconf.port_file->ptr)) {
|
||
if (errno != EACCES && errno != EPERM) {
|
||
log_error_write(srv, __FILE__, __LINE__, "sbds",
|
||
"unlink failed for:",
|
||
srv->srvconf.port_file,
|
||
errno,
|
||
strerror(errno));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
... | ... | |
}
|
||
}
|
||
}
|
||
if (srv->srvconf.port_file->used &&
|
||
srv->srvconf.changeroot->used == 0 &&
|
||
0 == graceful_shutdown) {
|
||
if (0 != unlink(srv->srvconf.port_file->ptr)) {
|
||
if (errno != EACCES && errno != EPERM) {
|
||
log_error_write(srv, __FILE__, __LINE__, "sbds",
|
||
"unlink failed for:",
|
||
srv->srvconf.port_file,
|
||
errno,
|
||
strerror(errno));
|
||
}
|
||
}
|
||
}
|
||
#ifdef HAVE_SIGACTION
|
||
log_error_write(srv, __FILE__, __LINE__, "sdsd",
|