sock: in listen_sock(), add debug message when socket() call failed.
[obnox/tinyproxy.git] / src / transparent-proxy.c
1 /* tinyproxy - A fast light-weight HTTP proxy
2  * Copyright (C) 2002       Petr Lampa <lampa@fit.vutbr.cz>
3  * Copyright (C) 2008       Robert James Kaes <rjk@wormbytes.ca>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19
20 /*
21  * This section of code is used for the transparent proxy option.  You will
22  * need to configure your firewall to redirect all connections for HTTP
23  * traffic to tinyproxy for this to work properly.
24  */
25
26 #include "transparent-proxy.h"
27 #include "conns.h"
28 #include "heap.h"
29 #include "html-error.h"
30 #include "log.h"
31 #include "reqs.h"
32 #include "text.h"
33 #include "conf.h"
34
35 /*
36  * Build a URL from parts.
37  */
38 static int build_url (char **url, const char *host, int port, const char *path)
39 {
40         int len;
41
42         assert (url != NULL);
43         assert (host != NULL);
44         assert (port > 0 && port < 32768);
45         assert (path != NULL);
46
47         len = strlen (host) + strlen (path) + 14;
48         *url = (char *) safemalloc (len);
49         if (*url == NULL)
50                 return -1;
51
52         return snprintf (*url, len, "http://%s:%d%s", host, port, path);
53 }
54
55 int
56 do_transparent_proxy (struct conn_s *connptr, hashmap_t hashofheaders,
57                       struct request_s *request, struct config_s *conf,
58                       char **url)
59 {
60         socklen_t length;
61         char *data;
62         size_t ulen = strlen (*url);
63
64         length = hashmap_entry_by_key (hashofheaders, "host", (void **) &data);
65         if (length <= 0) {
66                 struct sockaddr_in dest_addr;
67
68                 if (getsockname
69                     (connptr->client_fd, (struct sockaddr *) &dest_addr,
70                      &length) < 0) {
71                         log_message (LOG_ERR,
72                                      "process_request: cannot get destination IP for %d",
73                                      connptr->client_fd);
74                         indicate_http_error (connptr, 400, "Bad Request",
75                                              "detail", "Unknown destination",
76                                              "url", *url, NULL);
77                         return 0;
78                 }
79
80                 request->host = (char *) safemalloc (17);
81                 strlcpy (request->host, inet_ntoa (dest_addr.sin_addr), 17);
82
83                 request->port = ntohs (dest_addr.sin_port);
84
85                 request->path = (char *) safemalloc (ulen + 1);
86                 strlcpy (request->path, *url, ulen + 1);
87
88                 build_url (url, request->host, request->port, request->path);
89                 log_message (LOG_INFO,
90                              "process_request: trans IP %s %s for %d",
91                              request->method, *url, connptr->client_fd);
92         } else {
93                 request->host = (char *) safemalloc (length + 1);
94                 if (sscanf (data, "%[^:]:%hu", request->host, &request->port) !=
95                     2) {
96                         strlcpy (request->host, data, length + 1);
97                         request->port = HTTP_PORT;
98                 }
99
100                 request->path = (char *) safemalloc (ulen + 1);
101                 strlcpy (request->path, *url, ulen + 1);
102
103                 build_url (url, request->host, request->port, request->path);
104                 log_message (LOG_INFO,
105                              "process_request: trans Host %s %s for %d",
106                              request->method, *url, connptr->client_fd);
107         }
108         if (conf->ipAddr && strcmp (request->host, conf->ipAddr) == 0) {
109                 log_message (LOG_ERR,
110                              "process_request: destination IP is localhost %d",
111                              connptr->client_fd);
112                 indicate_http_error (connptr, 400, "Bad Request",
113                                      "detail",
114                                      "You tried to connect to the machine "
115                                      "the proxy is running on", "url", *url,
116                                      NULL);
117                 return 0;
118         }
119
120         return 1;
121 }