00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "apr_network_io.h"
00018 #include "apr_strings.h"
00019
00020 #define APR_WANT_STRFUNC
00021 #include "apr_want.h"
00022
00023 #define CORE_PRIVATE
00024 #include "ap_config.h"
00025 #include "httpd.h"
00026 #include "http_config.h"
00027 #include "ap_listen.h"
00028 #include "http_log.h"
00029 #include "mpm.h"
00030 #include "mpm_common.h"
00031
00032 ap_listen_rec *ap_listeners = NULL;
00033
00034 #if APR_HAVE_IPV6
00035 static int default_family = APR_UNSPEC;
00036 #else
00037 static int default_family = APR_INET;
00038 #endif
00039
00040 static ap_listen_rec *old_listeners;
00041 static int ap_listenbacklog;
00042 static int send_buffer_size;
00043
00044
00045 static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server)
00046 {
00047 apr_socket_t *s = server->sd;
00048 int one = 1;
00049 #if APR_HAVE_IPV6
00050 #ifdef AP_ENABLE_V4_MAPPED
00051 int v6only_setting = 0;
00052 #else
00053 int v6only_setting = 1;
00054 #endif
00055 #endif
00056 apr_status_t stat;
00057
00058 #ifndef WIN32
00059 stat = apr_socket_opt_set(s, APR_SO_REUSEADDR, one);
00060 if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
00061 ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
00062 "make_sock: for address %pI, apr_socket_opt_set: (SO_REUSEADDR)",
00063 server->bind_addr);
00064 apr_socket_close(s);
00065 return stat;
00066 }
00067 #endif
00068
00069 stat = apr_socket_opt_set(s, APR_SO_KEEPALIVE, one);
00070 if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
00071 ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
00072 "make_sock: for address %pI, apr_socket_opt_set: (SO_KEEPALIVE)",
00073 server->bind_addr);
00074 apr_socket_close(s);
00075 return stat;
00076 }
00077
00078 #if APR_HAVE_IPV6
00079 if (server->bind_addr->family == APR_INET6) {
00080 stat = apr_socket_opt_set(s, APR_IPV6_V6ONLY, v6only_setting);
00081 if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
00082 ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
00083 "make_sock: for address %pI, apr_socket_opt_set: "
00084 "(IPV6_V6ONLY)",
00085 server->bind_addr);
00086 apr_socket_close(s);
00087 return stat;
00088 }
00089 }
00090 #endif
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 if (send_buffer_size) {
00112 stat = apr_socket_opt_set(s, APR_SO_SNDBUF, send_buffer_size);
00113 if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
00114 ap_log_perror(APLOG_MARK, APLOG_WARNING, stat, p,
00115 "make_sock: failed to set SendBufferSize for "
00116 "address %pI, using default",
00117 server->bind_addr);
00118
00119 }
00120 }
00121
00122 #if APR_TCP_NODELAY_INHERITED
00123 ap_sock_disable_nagle(s);
00124 #endif
00125
00126 if ((stat = apr_bind(s, server->bind_addr)) != APR_SUCCESS) {
00127 ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, stat, p,
00128 "make_sock: could not bind to address %pI",
00129 server->bind_addr);
00130 apr_socket_close(s);
00131 return stat;
00132 }
00133
00134 if ((stat = apr_listen(s, ap_listenbacklog)) != APR_SUCCESS) {
00135 ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, stat, p,
00136 "make_sock: unable to listen for connections "
00137 "on address %pI",
00138 server->bind_addr);
00139 apr_socket_close(s);
00140 return stat;
00141 }
00142
00143 #ifdef WIN32
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 stat = apr_socket_opt_set(s, APR_SO_REUSEADDR, one);
00155 if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
00156 ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
00157 "make_sock: for address %pI, apr_socket_opt_set: (SO_REUSEADDR)",
00158 server->bind_addr);
00159 apr_socket_close(s);
00160 return stat;
00161 }
00162 #endif
00163
00164 #if APR_HAS_SO_ACCEPTFILTER
00165 #ifndef ACCEPT_FILTER_NAME
00166 #define ACCEPT_FILTER_NAME "httpready"
00167 #ifdef __FreeBSD_version
00168 #if __FreeBSD_version < 411000
00169 #undef ACCEPT_FILTER_NAME
00170 #define ACCEPT_FILTER_NAME "dataready"
00171 #endif
00172 #endif
00173 #endif
00174 apr_socket_accept_filter(s, ACCEPT_FILTER_NAME, "");
00175 #endif
00176
00177 server->sd = s;
00178 server->active = 1;
00179
00180 #ifdef MPM_ACCEPT_FUNC
00181 server->accept_func = MPM_ACCEPT_FUNC;
00182 #else
00183 server->accept_func = NULL;
00184 #endif
00185
00186 return APR_SUCCESS;
00187 }
00188
00189 static apr_status_t close_listeners_on_exec(void *v)
00190 {
00191 ap_listen_rec *lr;
00192
00193 for (lr = ap_listeners; lr; lr = lr->next) {
00194 apr_socket_close(lr->sd);
00195 lr->active = 0;
00196 }
00197
00198 return APR_SUCCESS;
00199 }
00200
00201
00202 static void find_default_family(apr_pool_t *p)
00203 {
00204 #if APR_HAVE_IPV6
00205
00206
00207
00208
00209
00210
00211
00212 if (default_family == APR_UNSPEC) {
00213 apr_status_t sock_rv;
00214 apr_socket_t *tmp_sock;
00215 apr_sockaddr_t *sa;
00216
00217 if ((sock_rv = apr_socket_create(&tmp_sock, APR_INET6, SOCK_STREAM, p))
00218 == APR_SUCCESS &&
00219 apr_sockaddr_info_get(&sa, NULL, APR_INET6, 0, 0, p) == APR_SUCCESS &&
00220 apr_bind(tmp_sock, sa) == APR_SUCCESS) {
00221 default_family = APR_INET6;
00222 }
00223 else {
00224 default_family = APR_INET;
00225 }
00226 if (sock_rv == APR_SUCCESS) {
00227 apr_socket_close(tmp_sock);
00228 }
00229 }
00230 #endif
00231 }
00232
00233
00234 static const char *alloc_listener(process_rec *process, char *addr, apr_port_t port)
00235 {
00236 ap_listen_rec **walk;
00237 ap_listen_rec *new;
00238 apr_status_t status;
00239 apr_port_t oldport;
00240 apr_sockaddr_t *sa;
00241
00242 if (!addr) {
00243 find_default_family(process->pool);
00244 switch(default_family) {
00245 case APR_INET:
00246 addr = "0.0.0.0";
00247 break;
00248
00249 #if APR_HAVE_IPV6
00250 case APR_INET6:
00251 addr = "::";
00252 break;
00253 #endif
00254
00255 default:
00256 ap_assert(1 != 1);
00257 }
00258 }
00259
00260
00261 for (walk = &old_listeners; *walk; walk = &(*walk)->next) {
00262 sa = (*walk)->bind_addr;
00263
00264 if (sa) {
00265 apr_sockaddr_port_get(&oldport, sa);
00266 if (!strcmp(sa->hostname, addr) && port == oldport) {
00267
00268 new = *walk;
00269 *walk = new->next;
00270 new->next = ap_listeners;
00271 ap_listeners = new;
00272 return NULL;
00273 }
00274 }
00275 }
00276
00277
00278 new = apr_palloc(process->pool, sizeof(ap_listen_rec));
00279 new->active = 0;
00280 if ((status = apr_sockaddr_info_get(&new->bind_addr, addr, APR_UNSPEC,
00281 port, 0, process->pool))
00282 != APR_SUCCESS) {
00283 ap_log_perror(APLOG_MARK, APLOG_CRIT, status, process->pool,
00284 "alloc_listener: failed to set up sockaddr for %s",
00285 addr);
00286 return "Listen setup failed";
00287 }
00288 if ((status = apr_socket_create(&new->sd,
00289 new->bind_addr->family,
00290 SOCK_STREAM, process->pool))
00291 != APR_SUCCESS) {
00292 ap_log_perror(APLOG_MARK, APLOG_CRIT, status, process->pool,
00293 "alloc_listener: failed to get a socket for %s", addr);
00294 return "Listen setup failed";
00295 }
00296
00297 new->next = ap_listeners;
00298 ap_listeners = new;
00299 return NULL;
00300 }
00301
00302 static int ap_listen_open(apr_pool_t *pool, apr_port_t port)
00303 {
00304 ap_listen_rec *lr;
00305 ap_listen_rec *next;
00306 int num_open;
00307 const char *userdata_key = "ap_listen_open";
00308 void *data;
00309
00310
00311
00312
00313
00314 num_open = 0;
00315 for (lr = ap_listeners; lr; lr = lr->next) {
00316 if (lr->active) {
00317 ++num_open;
00318 }
00319 else {
00320 if (make_sock(pool, lr) == APR_SUCCESS) {
00321 ++num_open;
00322 lr->active = 1;
00323 }
00324 else {
00325
00326 return -1;
00327 }
00328 }
00329 }
00330
00331
00332 for (lr = old_listeners; lr; lr = next) {
00333 apr_socket_close(lr->sd);
00334 lr->active = 0;
00335 next = lr->next;
00336 }
00337 old_listeners = NULL;
00338
00339 #if AP_NONBLOCK_WHEN_MULTI_LISTEN
00340
00341
00342
00343
00344
00345 if (ap_listeners && ap_listeners->next) {
00346 for (lr = ap_listeners; lr; lr = lr->next) {
00347 apr_status_t status;
00348
00349 status = apr_socket_opt_set(lr->sd, APR_SO_NONBLOCK, 1);
00350 if (status != APR_SUCCESS) {
00351 ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, status, pool,
00352 "ap_listen_open: unable to make socket non-blocking");
00353 return -1;
00354 }
00355 }
00356 }
00357 #endif
00358
00359
00360
00361
00362
00363 apr_pool_userdata_get(&data, userdata_key, pool);
00364 if (!data) {
00365 apr_pool_userdata_set((const void *)1, userdata_key,
00366 apr_pool_cleanup_null, pool);
00367 apr_pool_cleanup_register(pool, NULL, apr_pool_cleanup_null,
00368 close_listeners_on_exec);
00369 }
00370
00371 return num_open ? 0 : -1;
00372 }
00373
00374 int ap_setup_listeners(server_rec *s)
00375 {
00376 ap_listen_rec *lr;
00377 int num_listeners = 0;
00378
00379 if (ap_listen_open(s->process->pool, s->port)) {
00380 return 0;
00381 }
00382
00383 for (lr = ap_listeners; lr; lr = lr->next) {
00384 num_listeners++;
00385 }
00386
00387 return num_listeners;
00388 }
00389
00390 void ap_listen_pre_config(void)
00391 {
00392 old_listeners = ap_listeners;
00393 ap_listeners = NULL;
00394 ap_listenbacklog = DEFAULT_LISTENBACKLOG;
00395 }
00396
00397
00398 const char *ap_set_listener(cmd_parms *cmd, void *dummy, const char *ips)
00399 {
00400 char *host, *scope_id;
00401 apr_port_t port;
00402 apr_status_t rv;
00403 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
00404
00405 if (err != NULL) {
00406 return err;
00407 }
00408
00409 rv = apr_parse_addr_port(&host, &scope_id, &port, ips, cmd->pool);
00410 if (rv != APR_SUCCESS) {
00411 return "Invalid address or port";
00412 }
00413
00414 if (host && !strcmp(host, "*")) {
00415 host = NULL;
00416 }
00417
00418 if (scope_id) {
00419
00420 return "Scope id is not supported";
00421 }
00422
00423 if (!port) {
00424 return "Port must be specified";
00425 }
00426
00427 return alloc_listener(cmd->server->process, host, port);
00428 }
00429
00430 const char *ap_set_listenbacklog(cmd_parms *cmd, void *dummy, const char *arg)
00431 {
00432 int b;
00433 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
00434
00435 if (err != NULL) {
00436 return err;
00437 }
00438
00439 b = atoi(arg);
00440 if (b < 1) {
00441 return "ListenBacklog must be > 0";
00442 }
00443
00444 ap_listenbacklog = b;
00445 return NULL;
00446 }
00447
00448 const char *ap_set_send_buffer_size(cmd_parms *cmd, void *dummy,
00449 const char *arg)
00450 {
00451 int s = atoi(arg);
00452 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
00453
00454 if (err != NULL) {
00455 return err;
00456 }
00457
00458 if (s < 512 && s != 0) {
00459 return "SendBufferSize must be >= 512 bytes, or 0 for system default.";
00460 }
00461
00462 send_buffer_size = s;
00463 return NULL;
00464 }