Project

General

Profile

Feature #1908 ยป lighttpd-1.4.21-random-port.patch

patch implements random-port feature - cdumke, 2009-02-19 15:26

View differences:

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",
    (1-1/1)