]> git.ipfire.org Git - thirdparty/squid.git/blame - src/IPInterception.cc
Document the 'carp' cache_peer option
[thirdparty/squid.git] / src / IPInterception.cc
CommitLineData
c8be6d7b 1
2/*
3f38a55e 3 * $Id: IPInterception.cc,v 1.5 2003/02/21 19:53:01 hno 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
83clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst)
84{
c8be6d7b 85 struct natlookup natLookup;
86 static int natfd = -1;
87 static int siocgnatl_cmd = SIOCGNATL & 0xff;
88 int x;
3f38a55e 89
c8be6d7b 90 natLookup.nl_inport = me.sin_port;
91 natLookup.nl_outport = peer.sin_port;
92 natLookup.nl_inip = me.sin_addr;
93 natLookup.nl_outip = peer.sin_addr;
94 natLookup.nl_flags = IPN_TCP;
95 if (natfd < 0) {
96 int save_errno;
97 enter_suid();
98 natfd = open(IPL_NAT, O_RDONLY, 0);
99 save_errno = errno;
100 leave_suid();
101 errno = save_errno;
102 }
103 if (natfd < 0) {
3f38a55e 104 debug(50, 1) ("parseHttpRequest: NAT open failed: %s\n",
c8be6d7b 105 xstrerror());
3f38a55e 106 return -1;
c8be6d7b 107 }
3f38a55e 108 /*
c8be6d7b 109 * IP-Filter changed the type for SIOCGNATL between
110 * 3.3 and 3.4. It also changed the cmd value for
111 * SIOCGNATL, so at least we can detect it. We could
112 * put something in configure and use ifdefs here, but
113 * this seems simpler.
114 */
115 if (63 == siocgnatl_cmd) {
116 struct natlookup *nlp = &natLookup;
117 x = ioctl(natfd, SIOCGNATL, &nlp);
118 } else {
119 x = ioctl(natfd, SIOCGNATL, &natLookup);
120 }
121 if (x < 0) {
122 if (errno != ESRCH) {
3f38a55e 123 debug(50, 1) ("parseHttpRequest: NAT lookup failed: ioctl(SIOCGNATL)\n");
c8be6d7b 124 close(natfd);
125 natfd = -1;
3f38a55e 126 }
127 return -1;
c8be6d7b 128 } else {
3f38a55e 129 if (me.sin_addr.s_addr != natLookup.nl_realip.s_addr)
130 dst->sin_family = AF_INET;
131 dst->sin_port = natLookup.nl_realport;
132 dst->sin_addr = natLookup.nl_realip;
133 return 0;
134 } else {
135 return -1;
136 }
c8be6d7b 137 }
3f38a55e 138}
139#elif LINUX_NETFILTER
140int
141clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst)
142{
143 size_t sock_sz = sizeof(*dst);
144 memcpy(dst, &me, sizeof(*dst));
145 if (getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, dst, &sock_sz) != 0)
146 return -1;
147
148 debug(33, 5) ("clientNatLookup: addr = %s", inet_ntoa(dst->sin_addr));
149 if (me.sin_addr.s_addr != dst->sin_addr.s_addr)
150 return 0;
151 else
152 return -1;
153}
c8be6d7b 154#elif PF_TRANSPARENT
3f38a55e 155int
156clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst)
157{
158 struct pfioc_natlook nl;
159 static int pffd = -1;
c8be6d7b 160 if (pffd < 0)
161 pffd = open("/dev/pf", O_RDWR);
162 if (pffd < 0) {
3f38a55e 163 debug(50, 1) ("parseHttpRequest: PF open failed: %s\n",
c8be6d7b 164 xstrerror());
3f38a55e 165 return -1;
c8be6d7b 166 }
3f38a55e 167 memset(dst, 0, sizeof(*dst));
c8be6d7b 168 memset(&nl, 0, sizeof(struct pfioc_natlook));
169 nl.saddr.v4.s_addr = peer.sin_addr.s_addr;
170 nl.sport = peer.sin_port;
171 nl.daddr.v4.s_addr = me.sin_addr.s_addr;
172 nl.dport = me.sin_port;
173 nl.af = AF_INET;
174 nl.proto = IPPROTO_TCP;
175 nl.direction = PF_OUT;
176 if (ioctl(pffd, DIOCNATLOOK, &nl)) {
177 if (errno != ENOENT) {
3f38a55e 178 debug(50, 1) ("parseHttpRequest: PF lookup failed: ioctl(DIOCNATLOOK)\n");
c8be6d7b 179 close(pffd);
180 pffd = -1;
3f38a55e 181 }
182 return -1;
183 } else {
184 int natted = me.sin_addr.s_addr != nt.rdaddr.v4.s_addr;
185 dst->sin_family = AF_INET;
186 dst->sin_port = nl.rdport;
187 dst->sin_addr = nl.rdaddr.v4;
188 if (natted)
189 return 0;
190 else
191 return -1;
192 }
193}
c8be6d7b 194#else
3f38a55e 195int
196clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst)
197{
198 debug(33, 1) ("WARNING: transparent proxying not supported\n");
199 return -1;
c8be6d7b 200}
3f38a55e 201#endif
202