]> git.ipfire.org Git - thirdparty/squid.git/blame - src/IPInterception.cc
Bug #829: icp denied query causes squid to fail assert src/HttpHeader.cc:374
[thirdparty/squid.git] / src / IPInterception.cc
CommitLineData
c8be6d7b 1
2/*
aa625860 3 * $Id: IPInterception.cc,v 1.9 2004/12/21 17:28:29 robertc Exp $
c8be6d7b 4 *
5 * DEBUG: section 89 NAT / IP Interception
6 * AUTHOR: Robert Collins
7 *
8 * SQUID Web Proxy Cache http://www.squid-cache.org/
9 * ----------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
33 *
34 */
35
36#include "squid.h"
37#include "clientStream.h"
68991eab 38#include "IPInterception.h"
c8be6d7b 39
40#if IPF_TRANSPARENT
41#if HAVE_SYS_IOCTL_H
42#include <sys/ioctl.h>
43#endif
44#include <netinet/tcp.h>
45#include <net/if.h>
46#if HAVE_IP_FIL_COMPAT_H
47#include <ip_fil_compat.h>
48#elif HAVE_NETINET_IP_FIL_COMPAT_H
49#include <netinet/ip_fil_compat.h>
50#elif HAVE_IP_COMPAT_H
51#include <ip_compat.h>
52#elif HAVE_NETINET_IP_COMPAT_H
53#include <netinet/ip_compat.h>
54#endif
55#if HAVE_IP_FIL_H
56#include <ip_fil.h>
57#elif HAVE_NETINET_IP_FIL_H
58#include <netinet/ip_fil.h>
59#endif
60#if HAVE_IP_NAT_H
61#include <ip_nat.h>
62#elif HAVE_NETINET_IP_NAT_H
63#include <netinet/ip_nat.h>
64#endif
65#endif
66
67#if PF_TRANSPARENT
68#include <sys/types.h>
69#include <sys/socket.h>
70#include <sys/ioctl.h>
71#include <sys/fcntl.h>
72#include <net/if.h>
73#include <netinet/in.h>
74#include <net/pfvar.h>
75#endif
76
77#if LINUX_NETFILTER
78#include <linux/netfilter_ipv4.h>
79#endif
80
c8be6d7b 81#if IPF_TRANSPARENT
3f38a55e 82int
62e76326 83
3f38a55e 84clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst)
85{
62e76326 86
c8be6d7b 87 struct natlookup natLookup;
88 static int natfd = -1;
89 static int siocgnatl_cmd = SIOCGNATL & 0xff;
90 int x;
3f38a55e 91
c8be6d7b 92 natLookup.nl_inport = me.sin_port;
93 natLookup.nl_outport = peer.sin_port;
94 natLookup.nl_inip = me.sin_addr;
95 natLookup.nl_outip = peer.sin_addr;
96 natLookup.nl_flags = IPN_TCP;
62e76326 97
98 if (natfd < 0)
99 {
100 int save_errno;
101 enter_suid();
102 natfd = open(IPL_NAT, O_RDONLY, 0);
103 save_errno = errno;
104 leave_suid();
105 errno = save_errno;
c8be6d7b 106 }
62e76326 107
108 if (natfd < 0)
109 {
110 debug(50, 1) ("parseHttpRequest: NAT open failed: %s\n",
111 xstrerror());
112 return -1;
c8be6d7b 113 }
62e76326 114
3f38a55e 115 /*
c8be6d7b 116 * IP-Filter changed the type for SIOCGNATL between
117 * 3.3 and 3.4. It also changed the cmd value for
118 * SIOCGNATL, so at least we can detect it. We could
119 * put something in configure and use ifdefs here, but
120 * this seems simpler.
121 */
62e76326 122 if (63 == siocgnatl_cmd)
123 {
124
125 struct natlookup *nlp = &natLookup;
126 x = ioctl(natfd, SIOCGNATL, &nlp);
127 } else
128 {
129 x = ioctl(natfd, SIOCGNATL, &natLookup);
130 }
131
132 if (x < 0)
133 {
134 if (errno != ESRCH) {
135 debug(50, 1) ("parseHttpRequest: NAT lookup failed: ioctl(SIOCGNATL)\n");
136 close(natfd);
137 natfd = -1;
138 }
139
140 return -1;
141 } else
142 {
143 if (me.sin_addr.s_addr != natLookup.nl_realip.s_addr)
144 dst->sin_family = AF_INET;
145
146 dst->sin_port = natLookup.nl_realport;
147
148 dst->sin_addr = natLookup.nl_realip;
149
150 return 0;
c8be6d7b 151 }
62e76326 152}
153
3f38a55e 154#elif LINUX_NETFILTER
155int
62e76326 156
3f38a55e 157clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst)
158{
159 size_t sock_sz = sizeof(*dst);
160 memcpy(dst, &me, sizeof(*dst));
62e76326 161
3f38a55e 162 if (getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, dst, &sock_sz) != 0)
62e76326 163 return -1;
3f38a55e 164
165 debug(33, 5) ("clientNatLookup: addr = %s", inet_ntoa(dst->sin_addr));
62e76326 166
3f38a55e 167 if (me.sin_addr.s_addr != dst->sin_addr.s_addr)
62e76326 168 return 0;
3f38a55e 169 else
62e76326 170 return -1;
3f38a55e 171}
62e76326 172
c8be6d7b 173#elif PF_TRANSPARENT
3f38a55e 174int
62e76326 175
3f38a55e 176clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst)
177{
62e76326 178
3f38a55e 179 struct pfioc_natlook nl;
180 static int pffd = -1;
62e76326 181
182 if (pffd < 0)
183 pffd = open("/dev/pf", O_RDWR);
184
c8be6d7b 185 if (pffd < 0)
62e76326 186 {
187 debug(50, 1) ("parseHttpRequest: PF open failed: %s\n",
188 xstrerror());
189 return -1;
c8be6d7b 190 }
62e76326 191
3f38a55e 192 memset(dst, 0, sizeof(*dst));
62e76326 193
c8be6d7b 194 memset(&nl, 0, sizeof(struct pfioc_natlook));
195 nl.saddr.v4.s_addr = peer.sin_addr.s_addr;
196 nl.sport = peer.sin_port;
197 nl.daddr.v4.s_addr = me.sin_addr.s_addr;
198 nl.dport = me.sin_port;
199 nl.af = AF_INET;
200 nl.proto = IPPROTO_TCP;
201 nl.direction = PF_OUT;
62e76326 202
203 if (ioctl(pffd, DIOCNATLOOK, &nl))
204 {
205 if (errno != ENOENT) {
206 debug(50, 1) ("parseHttpRequest: PF lookup failed: ioctl(DIOCNATLOOK)\n");
207 close(pffd);
208 pffd = -1;
209 }
210
211 return -1;
212 } else
213 {
482aa790 214 int natted = me.sin_addr.s_addr != nl.rdaddr.v4.s_addr;
62e76326 215 dst->sin_family = AF_INET;
216 dst->sin_port = nl.rdport;
217 dst->sin_addr = nl.rdaddr.v4;
218
219 if (natted)
220 return 0;
221 else
222 return -1;
3f38a55e 223 }
224}
62e76326 225
c8be6d7b 226#else
3f38a55e 227int
62e76326 228
3f38a55e 229clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst)
230{
231 debug(33, 1) ("WARNING: transparent proxying not supported\n");
232 return -1;
c8be6d7b 233}
62e76326 234
3f38a55e 235#endif
236