source: trunk/server/common/oursrc/httpdmods/mod_original_dst.c

Last change on this file was 2591, checked in by achernya, 10 years ago
Reintegrate fc20-dev into trunk
File size: 2.8 KB
Line 
1/* mod_original_dst
2 * version 1.0, released 2011-03-25
3 * Anders Kaseorg <andersk@mit.edu>
4 *
5 * This replaces the address of incoming connections with the original
6 * destination, before any local masquerading (as given by
7 * SO_ORIGINAL_DST).
8 */
9
10#include <sys/types.h>
11#include <sys/socket.h>
12#include <limits.h>
13#include <netdb.h>
14#include <linux/netfilter_ipv4.h>
15
16#include "ap_config.h"
17#include "ap_listen.h"
18#include "apr_portable.h"
19#include "http_config.h"
20#include "http_log.h"
21#include "httpd.h"
22#include "unixd.h"
23
24#define MPM_ACCEPT_FUNC ap_unixd_accept
25
26extern void apr_sockaddr_vars_set(apr_sockaddr_t *, int, apr_port_t);
27
28static apr_status_t original_dst_accept_func(void **accepted, ap_listen_rec *lr, apr_pool_t *ptrans)
29{
30    apr_status_t status = MPM_ACCEPT_FUNC(accepted, lr, ptrans);
31    if (status != APR_SUCCESS)
32        return status;
33
34    apr_socket_t *csd = *accepted;
35
36    apr_sockaddr_t *local_addr;
37    status = apr_socket_addr_get(&local_addr, APR_LOCAL, csd);
38    if (status != APR_SUCCESS) {
39        ap_log_perror(APLOG_MARK, APLOG_EMERG, status, ptrans,
40                      "original_dst_accept_func: apr_socket_addr_get failed");
41        apr_socket_close(csd);
42        return APR_EGENERAL;
43    }
44
45    int sockdes;
46    status = apr_os_sock_get(&sockdes, csd);
47    if (status != APR_SUCCESS) {
48        ap_log_perror(APLOG_MARK, APLOG_EMERG, status, ptrans,
49                      "original_dst_accept_func: apr_os_sock_get failed");
50        apr_socket_close(csd);
51        return APR_EGENERAL;
52    }
53
54    socklen_t salen = sizeof(local_addr->sa);
55    status = getsockopt(sockdes, SOL_IP, SO_ORIGINAL_DST, &local_addr->sa, &salen);
56    if (status == 0) {
57        local_addr->salen = salen;
58        apr_sockaddr_vars_set(local_addr, local_addr->sa.sin.sin_family, htons(local_addr->sa.sin.sin_port));
59        return APR_SUCCESS;
60    } else if (errno == ENOENT) {
61        return APR_SUCCESS;
62    } else {
63        ap_log_perror(APLOG_MARK, APLOG_EMERG, errno, ptrans,
64                      "original_dst_accept_func: getsockopt failed");
65        apr_socket_close(csd);
66        return APR_EGENERAL;
67    }
68}
69
70static int original_dst_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
71{
72    ap_listen_rec *lr;
73    for (lr = ap_listeners; lr; lr = lr->next)
74        if (lr->accept_func == MPM_ACCEPT_FUNC)
75            lr->accept_func = original_dst_accept_func;
76    return OK;
77}
78
79static void original_dst_register_hooks(apr_pool_t *p)
80{
81    ap_hook_post_config(original_dst_post_config, NULL, NULL, APR_HOOK_MIDDLE);
82}
83
84module AP_MODULE_DECLARE_DATA original_dst_module =
85{
86    STANDARD20_MODULE_STUFF,
87    NULL,                           /* per-directory config creator */
88    NULL,                           /* dir config merger */
89    NULL,                           /* server config creator */
90    NULL,                           /* server config merger */
91    NULL,                           /* command table */
92    original_dst_register_hooks,    /* set up other request processing hooks */
93};
Note: See TracBrowser for help on using the repository browser.